mybatis属性详解
前⾔
MyBatis是基于“结构不可控”的思想建⽴的,也就是我们希望数据库遵循第三范式或BCNF,但实际事与愿违,那么结果集映射就是MyBatis为我们提供这种理想与现实间转换的⼿段了,⽽resultMap就是结果集映射的配置标签了。
在深⼊ResultMap标签前,我们需要了解从SQL查询结果集到JavaBean或POJO实体的过程。
从SQL查询结果到领域模型实体
1. 通过JDBC查询得到ResultSet对象
2. 遍历ResultSet对象并将每⾏数据暂存到HashMap实例中,以结果集的字段名或字段别名为键,以字段值为值
3. 根据ResultMap标签的type属性通过反射实例化领域模型
4. 根据ResultMap标签的type属性和id、result等标签信息将HashMap中的键值对,填充到领域模型实例中并返回
⼀、resultMap
1、属性说明
id属性,resultMap标签的标识。
type属性,返回值的全限定类名,或类型别名。
autoMapping属性,值范围true(默认值)|false, 设置是否启动⾃动映射功能,⾃动映射功能就是⾃动查与字段名⼩写同名的属性名,并调⽤setter ⽅法。⽽设置为false后,则需要在resultMap内明确注明映射关系才会调⽤对应的setter⽅法。
2、基本作⽤:建⽴SQL查询结果字段与实体属性的映射关系
⽰例1:通过setter构造领域模型
public class EStudent{
private long id;
private String name;
private int age;
// getter,setter⽅法
/**
* 必须提供⼀个⽆参数的构造函数
*/
public EStudent(){}
}
<select id="getStudent" resultMap="getStudentRM">
SELECT ID, Name, Age
FROM TStudent
</select>
<resultMap id="getStudentRM" type="EStudnet">
<id property="id" column="ID"/>
<result property="studentName" column="Name"/>
补码相减<result property="studentAge" column="Age"/>
</resultMap>
jquery小游戏源码⼦元素说明:
id元素,⽤于设置主键字段与领域模型属性的映射关系
result元素,⽤于设置普通字段与领域模型属性的映射关系
id、result语句属性配置细节:
ignorecase属性属性描述
网页怎么制作property需要映射到JavaBean 的属性名称。
column数据表的列名或者标签别名。
javaType⼀个完整的类名,或者是⼀个类型别名。如果你匹配的是⼀个JavaBean,那MyBatis 通常会⾃⾏检测到。然后,如果你是要映射到⼀个HashMap,那你需要指定javaType 要达到的⽬的。mysql语句的执行顺序
jdbcType数据表⽀持的类型列表。这个属性只在insert,update 或delete 的时候针对允许空的列有⽤。JDBC 需要这项,但MyBatis 不需要。如果你是直接针对JDBC 编码,且有允许空的列,⽽你要指定这项。
typeHandler使⽤这个属性可以覆写类型处理器。这项值可以是⼀个完整的类名,也可以是⼀个类型别名。
⽰例2:通过构造函数构造领域模型
<select id="getStudent" resultMap="getStudentRM">
SELECT ID, Name, Age
FROM TStudent
</select>
<resultMap id="getStudentRM" type="EStudnet">
<constructor>
<idArg column="ID" javaType="_long"/>
<arg column="Name" javaType="String"/>
<arg column="Age" javaType="_int"/>
</constructor>
</resultMap>
⼦元素说明:
constructor元素,指定使⽤指定参数列表的构造函数来实例化领域模型。注意:其⼦元素顺序必须与参数列表顺序对应
idArg⼦元素,标记该⼊参为主键
arg⼦元素,标记该⼊参为普通字段(主键使⽤该⼦元素设置也是可以的)
3、⼀对⼀关系、⼀对多关系查询
注意:在采⽤嵌套结果的⽅式查询⼀对⼀、⼀对多关系时,必须要通过resultMap下的id或result标签来显式设置属性/字段映射关系,否则在查询多条记录时会仅仅返回最后⼀条记录的情况。association联合
联合元素⽤来处理“⼀对⼀”的关系。需要指定映射的实体类的属性,属性的javaType(通常MyBatis ⾃⼰会识别)。对应的数据库表的列名称。如果想覆写的话返回结果的值,需要指定typeHandler。
不同情况需要告诉MyBatis 如何加载⼀个联合。MyBatis 可以⽤两种⽅式加载:
select: 执⾏⼀个其它映射的SQL 语句返回⼀个Java实体类型。较灵活;
resultsMap: 使⽤⼀个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型。
例如,⼀个班级对应⼀个班主任。
⾸先定义好班级中的班主任private TeacherEntity teacherEntity;
使⽤select实现联合
例:班级实体类中有班主任的属性,通过联合在得到⼀个班级实体时,同时映射出班主任实体。
这样可以直接复⽤在l⽂件中定义好的查询teacher根据其ID的select语句。⽽且不需要修改写好的SQL语句,只需要直接修改resultMap 即可。
<resultMap type="ClassEntity" id="classResultMap">
<id property="classID" column="CLASS_ID" />
<result property="className" column="CLASS_NAME" />
<result property="classYear" column="CLASS_YEAR" />
<association property="teacherEntity" column="TEACHER_ID" select="getTeacher"/>
</resultMap>
<select id="getClassByID" parameterType="String" resultMap="classResultMap">
SELECT * FROM CLASS_TBL CT
WHERE CT.CLASS_ID = #{classID};
</select>
<resultMap type="TeacherEntity" id="teacherResultMap">
<id property="teacherID" column="TEACHER_ID" />
<result property="teacherName" column="TEACHER_NAME" />
<result property="teacherSex" column="TEACHER_SEX" />
<result property="teacherBirthday" column="TEACHER_BIRTHDAY"/>
<result property="workDate" column="WORK_DATE"/>
<result property="professional" column="PROFESSIONAL"/>
</resultMap>
<select id="getTeacher" parameterType="String" resultMap="teacherResultMap">
SELECT *
FROM TEACHER_TBL TT
WHERE TT.TEACHER_ID = #{teacherID}
</select>
使⽤resultMap实现联合
与上⾯同样的功能,查询班级,同时查询器班主任。需在association中添加resultMap(在teacher的xml⽂件中定义好的),新写sql(查询班级表left join 教师表),不需要teacher的select。
修改l⽂件部分内容:
<resultMap type="ClassEntity" id="classResultMap">
<id property="classID" column="CLASS_ID" />
<result property="className" column="CLASS_NAME" />
<result property="classYear" column="CLASS_YEAR" />
<association property="teacherEntity" column="TEACHER_ID" resultMap="teacherResultMap"/>
</resultMap>
<select id="getClassAndTeacher" parameterType="String" resultMap="classResultMap">
SELECT *
FROM CLASS_TBL CT LEFT JOIN TEACHER_TBL TT ON CT.TEACHER_ID = TT.TEACHER_ID
WHERE CT.CLASS_ID = #{classID};
</select>
其中的teacherResultMap请见上⾯l⽂件部分内容中。
collection聚集
聚集元素⽤来处理“⼀对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(⼀般为ArrayList);列表中对象的类型ofType(Java实体类);对应的数据库表的列名称;
不同情况需要告诉MyBatis 如何加载⼀个聚集。MyBatis 可以⽤两种⽅式加载:
1. select: 执⾏⼀个其它映射的SQL 语句返回⼀个Java实体类型。较灵活;
2. resultsMap: 使⽤⼀个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型。
例如,⼀个班级有多个学⽣。
⾸先定义班级中的学⽣列表属性:private List<StudentEntity> studentList;
使⽤select实现聚集
⽤法和联合很类似,区别在于,这是⼀对多,所以⼀般映射过来的都是列表。所以这⾥需要定义javaType为ArrayList,还需要定义列表中对象的类型ofType,以及必须设置的select的语句名称(需要注意的是,这⾥的查询student的select语句条件必须是外键classID)。
<resultMap type="ClassEntity" id="classResultMap">
<id property="classID" column="CLASS_ID" />
<result property="className" column="CLASS_NAME" />
<result property="classYear" column="CLASS_YEAR" />
<association property="teacherEntity" column="TEACHER_ID" select="getTeacher"/>
<collection property="studentList" column="CLASS_ID" javaType="ArrayList" ofType="StudentEntity" select="getStudentByClassID"/>
</resultMap>
<select id="getClassByID" parameterType="String" resultMap="classResultMap">
SELECT * FROM CLASS_TBL CT
WHERE CT.CLASS_ID = #{classID};
</select>
<!-- java属性,数据库表字段之间的映射定义 -->
<resultMap type="StudentEntity" id="studentResultMap">
<id property="studentID" column="STUDENT_ID" />
<result property="studentName" column="STUDENT_NAME" />
<result property="studentSex" column="STUDENT_SEX" />
<result property="studentBirthday" column="STUDENT_BIRTHDAY" />
</resultMap>
<!-- 查询学⽣list,根据班级id -->
<select id="getStudentByClassID" parameterType="String" resultMap="studentResultMap">
<include refid="selectStudentAll" />
WHERE ST.CLASS_ID = #{classID}
</select>
使⽤resultMap实现聚集
使⽤resultMap,就需要重写⼀个sql,left join学⽣表。
<resultMap type="ClassEntity" id="classResultMap">
<id property="classID" column="CLASS_ID" />
<result property="className" column="CLASS_NAME" />
<result property="classYear" column="CLASS_YEAR" />
<association property="teacherEntity" column="TEACHER_ID" resultMap="teacherResultMap"/>
<collection property="studentList" column="CLASS_ID" javaType="ArrayList" ofType="StudentEntity" resultMap="studentResultMap"/>
</resultMap>
<select id="getClassAndTeacherStudent" parameterType="String" resultMap="classResultMap">
SELECT *
FROM CLASS_TBL CT
LEFT JOIN STUDENT_TBL ST
ON CT.CLASS_ID = ST.CLASS_ID
LEFT JOIN TEACHER_TBL TT
ON CT.TEACHER_ID = TT.TEACHER_ID
WHERE CT.CLASS_ID = #{classID};
</select>
其中的teacherResultMap请见上⾯l⽂件部分内容中。studentResultMap请见上⾯l⽂件部分内容中。
4. 动态映射关系
通过 discriminator⼦元素(鉴别器)可以实现动态映射关系信息的设置。具体⽰例如下:
public class EStudent{
private long id;
private String name;
private String juniorHighSchool;
private String seniorHighSchool;
private int during; // 在本校就读时间
// getter,setter⽅法
/**
* 必须提供⼀个⽆参数的构造函数
*/
public EStudent(){}
}
情景:查询学⽣信息的seniorHighSchool信息,若就读时间during字段值为4、5、6时,则以juniorHighSchool字段作所为seniorHighSchool信息。
<select id="getStundent" resultMap="rm">
SELECT ID, Name, JuniorHighSchool, SeniorHighSchool, during
FROM TStudent
</select>
<resultMap id="rm" type="EStudent">
// 若不加这句,则当将juniorHighSchool赋予给seniorHighSchool属性时,juniorHighSchool属性将为null
<result column="juniorHighSchool" property="juniorHighSchool"/>
数组名是指针常量吗<discriminator column="during" javaType="_int">
// 形式1:通过resultType设置动态映射信息
<case value="4" resultType="EStudent">
<result column="juniorHighSchool" property="seniorHighSchool"/>
</case>
// 形式2: 通过resultMap设置动态映射信息
<case value="5" resultMap="dynamicRM"/>
<case value="6" resultMap="dynamicRM"/>
</discriminator>
</resultMap>
<resultMap id="dynamicRM" type="EStudent">
<result column="juniorHighSchool" property="seniorHighSchool"/>
</resultMap>
注意:上⾯关于 discriminator⼦元素的 case元素的 resultType属性和 resultMap元素的 type属性,均不是直指返回的领域模型类型,⽽是指定根据判断条件后得到映射关系,可通过 id⼦元素和 result⼦元素重写映射关系。
5. id元素,result元素,idArg元素,arg元素,discriminator元素的共同属性
javaType属性:Java类的全限定名,或别名
jdbcType属性:JDBC类型, JDBC类型为CUD操作时列可能为空时进⾏处理
typeHandler属性:指定类型处理器的全限定类名或类型别名
column属性:指定SQL查询结果的字段名或字段别名。将⽤于JDBC的 String(columnName)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论