mybatis教程之resultmap_动力节点Java学院整理
sql 映射xml 文件是所有sql语句放置的地方。需要定义一个workspace,一般定义为对应的接口类的路径。写好sql语句映射文件后,需要在mybatis配置文件mappers标签中引用,例如:
<mappers> <mapper resource="com/bjpowernode/manager/data/mappers/usermapper.xml" /> <mapper resource="com/bjpowernode/manager/data/mappers/studentmapper.xml" /> <mapper resource="com/bjpowernode/manager/data/mappers/classmapper.xml" /> <mapper resource="com/bjpowernode/manager/data/mappers/teachermapper.xml" /> </mappers>
当java接口与xml文件在一个相对路径下时,可以不在mybatis配置文件的mappers中声明。
sql 映射xml 文件一些初级的元素:
1. cache – 配置给定模式的缓存
2. cache-ref – 从别的模式中引用一个缓存
3. resultmap – 这是最复杂而却强大的一个元素了,它描述如何从结果集中加载对象
4. sql – 一个可以被其他语句复用的sql 块
5. insert – 映射insert 语句
6. update – 映射update 语句
7. delete – 映射deleete 语句
8. select - 映射select语句
2.1 resultmap
resultmap 是mybatis 中最重要最强大的元素了。你可以让你比使用jdbc 调用结果集省掉90%的代码,也可以让你做许多jdbc 不支持的事。现实上,要写一个等同类似于交互的映射这样的复杂语句,可能要上千行的代码。resultmaps 的目的,就是这样简单的语句而不需要多余的结果映射,更多复杂的语句,除了只要一些绝对必须的语句描述关系以外,再也不需要其它的。
resultmap属性:type为java实体类;id为此resultmap的标识。
resultmap可以设置的映射:
1. constructor – 用来将结果反射给一个实例化好的类的构造器
a) idarg – id 参数;将结果集标记为id,以方便全局调用
b) arg –反射到构造器的通常结果
2. id – id 结果,将结果集标记为id,以方便全局调用
3. result – 反射到javabean 属性的普通结果
4. association – 复杂类型的结合;多个结果合成的类型
a) nested result mappings – 几resultmap 自身嵌套关联,也可以引用到一个其它上
5. collection –复杂类型集合a collection of complex types
6. nested result mappings – resultmap 的集合,也可以引用到一个其它上
7. discriminator – 使用一个结果值以决定使用哪个resultmap
a) case – 基本一些值的结果映射的case 情形
i. nested result mappings –一个case 情形本身就是一个结果映射,因此也可以包括一些相同的元素,也可以引用一个外部resultmap。
id、result
id、result是最简单的映射,id为主键映射;result其他基本数据库表字段到实体类属性的映射。
最简单的例子:
<resultmap type="bjpowernodestudentmanagerdatamodelstudententity" id="studentresultmap"> <id property="studentid" column="student_id" javatype="string" jdbctype="varchar"/> <result property="studentname" column="student_name" javatype="string" jdbctype="varchar"/> <result property="studentsex" column="student_sex" javatype="int" jdbctype="integer"/> <result property="studentbirthday" column="student_birthday" javatype="date" jdbctype="date"/> <result property="studentphoto" column="student_photo" javatype="byte[]" jdbctype="blob" typehandler="orgapacheibatistypeblobtypehandler" /> </resultmap>
id、result语句属性配置细节:
属性 描述
属性
|
描述
|
|
property
|
需要映射到javabean 的属性名称。
|
|
column
|
数据表的列名或者标签别名。
|
|
javatype
|
一个完整的类名,或者是一个类型别名。如果你匹配的是一个javabean,那mybatis 通常会自行检测到。然后,如果你是要映射到一个hashmap,那你需要指定javatype 要达到的目的。
|
|
jdbctype
|
数据表支持的类型列表。这个属性只在insert,update 或delete 的时候针对允许空的列有用。jdbc 需要这项,但mybatis 不需要。如果你是直接针对jdbc 编码,且有允许空的列,而你要指定这项。
|
|
typehandler
|
使用这个属性可以覆写类型处理器。这项值可以是一个完整的类名,也可以是一个类型别名。
|
|
支持的jdbc类型
为了将来的引用,mybatis 支持下列jdbc 类型,通过jdbctype 枚举:
bit,float,char,timestamp,other,undefined,tinyint,real,varchar,binary,blob,nvarchar,smallint,double,longvarchar,varbinary,clob,nchar,integer,numeric,date,longvarbinary,boolean,nclob,bigint,decimal,time,null,cursor
constructor
我们使用id、result时候,需要定义java实体类的属性映射到数据库表的字段上。这个时候是使用javabean实现的。当然我们也可以使用实体类的构造方法来实现值的映射,这个时候是通过构造方法参数的书写的顺序来进行赋值的。
使用construcotr功能有限(例如使用collection级联查询)。
上面使用id、result实现的功能就可以改为:
<resultmap type="studententity" id="studentresultmap" > <constructor> <idarg javatype="string" column="student_id"/> <arg javatype="string" column="student_name"/> <arg javatype="string" column="student_sex"/> <arg javatype="date" column="student_birthday"/> </constructor> </resultmap>
当然,我们需要定义studententity实体类的构造方法:
public studententity(string studentid, string studentname, string studentsex, date studentbirthday){ this.studentid = studentid; this.studentname = studentname; this.studentsex = studentsex; this.studentbirthday = studentbirthday; }
association联合
联合元素用来处理“一对一”的关系。需要指定映射的java实体类的属性,属性的javatype(通常mybatis 自己会识别)。对应的数据库表的列名称。如果想覆写的话返回结果的值,需要指定typehandler。
不同情况需要告诉mybatis 如何加载一个联合。mybatis 可以用两种方式加载:
1. select: 执行一个其它映射的sql 语句返回一个java实体类型。较灵活;
2. resultsmap: 使用一个嵌套的结果映射来处理通过join查询结果集,映射成java实体类型。
例如,一个班级对应一个班主任。
首先定义好班级中的班主任属性:
private teacherentity teacherentity;
使用select实现联合
例:班级实体类中有班主任的属性,通过联合在得到一个班级实体时,同时映射出班主任实体。
这样可以直接复用在teachermapper.xml文件中定义好的查询teacher根据其id的select语句。而且不需要修改写好的sql语句,只需要直接修改resultmap即可。
classmapper.xml文件部分内容:
<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 ctclass_id = #{classid}; </select>
teachermapper.xml文件部分内容:
<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。
修改classmapper.xml文件部分内容:
<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请见上面teachermapper.xml文件部分内容中。
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)。
classmapper.xml文件部分内容:
<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>
studentmapper.xml文件部分内容:
<!-- 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 stclass_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请见上面teachermapper.xml文件部分内容中。studentresultmap请见上面studentmapper.xml文件部分内容中。
discriminator鉴别器
有时一个单独的数据库查询也许返回很多不同(但是希望有些关联)数据类型的结果集。鉴别器元素就是被设计来处理这个情况的,还有包括类的继承层次结构。鉴别器非常容易理解,因为它的表现很像java语言中的switch语句。
定义鉴别器指定了column和javatype属性。列是mybatis查找比较值的地方。javatype是需要被用来保证等价测试的合适类型(尽管字符串在很多情形下都会有用)。
下面这个例子为,当classid为20000001时,才映射classid属性。
<resultmap type="bjpowernodestudentmanagerdatamodelstudententity" id="resultmap_studententity_discriminator"> <id property="studentid" column="student_id" javatype="string" jdbctype="varchar"/> <result property="studentname" column="student_name" javatype="string" jdbctype="varchar"/> <result property="studentsex" column="student_sex" javatype="int" jdbctype="integer"/> <result property="studentbirthday" column="student_birthday" javatype="date" jdbctype="date"/> <result property="studentphoto" column="student_photo" javatype="byte[]" jdbctype="blob" typehandler="orgapacheibatistypeblobtypehandler" /> <result property="placeid" column="place_id" javatype="string" jdbctype="varchar"/> <discriminator column="class_id" javatype="string" jdbctype="varchar"> <case value="20000001" resulttype="bjpowernodestudentmanagerdatamodelstudententity" > <result property="classid" column="class_id" javatype="string" jdbctype="varchar"/> </case> </discriminator> </resultmap>
上一篇: MySQL数据类型varchar详解
推荐阅读