天天看点

MyBatis关联映射

书接上文。

在实际使用数据库过程中,使用最多的应该就是查询了,还一些复杂的查询。比如,表的内链接(INNER JOIN),交叉连接(CROSS JOIN),自连接,左外连接(LEFT OUTER JOIN),右外连接(RIGHT OUTER JOIN), 全外连接(FULL OUTER JOIN)。这些查询的数据如何用MyBatis进行显示呢?

ResultMap元素是MyBatis中最重要的最强大的元素,它的作用是告诉MyBatis,从结果集中取出的数据要怎样安置。就像是JDBC中ResultSet中取出的一个元组,使用哪些变量去存储其中的每一个属性值。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0 //EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="qiqihaer.mybatis.mapper.PersonMapper">
	<!-- 根据id查询Person 返回ResultMap -->
	<select id="selectPersonById" parameterType="int" resultMap="personMap">
		SELECT * FROM t_person WHERE id = #{id}
	</select>
	
	<resultMap id="personMap" type="qiqihaer.mybatis.domain.Person">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<!-- 关联映射,一对一 -->
		<association property="card" column="card_id" 
			select="qiqihaer.mybatis.mapper.CardMapper.selectCardById"
			javaType="qiqihaer.mybatis.domain.Card"/>
	</resultMap>
</mapper>
           

看到第一条的select没有了属性resultType取而代之的是resultMap,表示查询返回的数据存储到一个Map集合。集合的内容是接下来的resultMap标签对应的内容。resultMap里面的 数据通过get()和set()方法将数据封装成type属性中指定的类型。resultMap标签里面的id标签标示数据库表的主键。result用来标记其他的属性,property表示type指定的返回类型 的属性。column就是数据库中的类型。

就这条语句来说就是,把sql语句select查询的内容封装成Person对象,Person对象中的id属性对应数据库表中查询出的主键值,数据库中查询到的name,sex,age属性分别对应Person中的name,sex,age属性。则个特别适合数据库表中的数据名和封装类型属性名不匹配的情况。

resultMap中还有一个association标签。这就是关联映射的一个例子,Person对象中有一个属性是身份证Card,Card是一个对象。在数据库中存储的时候,显然,t_person中只是存储一个外键,指向 t_card的主键。但是我们生成Person的时候是想要一个完整的Card对象的。associate就是解决这个问题的,像是在查询中再次嵌套一层查询。property,column功能不变,select指向嵌套的查询的语句,javaType表示,嵌套查询结果封装的类型。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0 //EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="qiqihaer.mybatis.mapper.CardMapper">
	<!-- 根据id查询card,返回的是 Card对象 -->
	<select id="selectCardById" parameterType="int" resultType="qiqihaer.mybatis.domain.Card">
		SELECT * FROM t_card WHERE id = #{id}
	</select>
</mapper>
           

qiqihaer.mybatis.mapper.CardMapper中也就只有这么一个selectCardById 查询语句。

还有一种情况,需要使用关联映射。

数据库中有一张班级表和一张学生表,很明显,班级表中的一个班级号,在学生表中对应多名学生。对应到Clazz类中学生属性应该是使用一个集合存储的。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0 //EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="qiqihaer.mybatis.mapper.ClazzMapper">
	<!-- 根据id查询班级的信息,返回的是resultMap -->
	<select id="selectClazzById" parameterType="int" resultMap="clazzResultMap">
		SELECT * FROM tb_clazz WHERE id = #{id}
	</select>
	<resultMap id="clazzResultMap" type="qiqihaer.mybatis.domain.Clazz">
		<id property="id" column="id"/>
		<result property="code" column="code"/>
		<result property="name" column="name"/>
		<!-- 一对多关联映射:fetchType="lazy"表示懒加载 
		这里的column是id,也就是使用数据库中查询到的 班级id当作参数传递-->
		<collection property="students" column="id" 
			javaType="ArrayList" ofType="qiqihaer.mybatis.domain.Student"
			select="qiqihaer.mybatis.mapper.StudentMapper.selectStudentByClazzId"
			fetchType="lazy">
			<!-- <id property="id" column="id"/>
			<result property="name" column="name"/>
			<result property="sex" column="sex"/>
			<result property="age" column="age"/>	 -->
		</collection>
	</resultMap>
</mapper>
           

这里就是把上面的的associate标签编程了collection标签,javaType属性由javaType和ofType组合代替,javaType表示存储使用的集合类型,ofType表示集合中的值。select指明集合中的值如何获取。fetchType属性取值由lazy和eager,eager表示立即加载,lazy表示懒加载,其不会立即发送sql语句去查询,而是等到需要的时候采取查询,正常这样的一对多的都是用懒加载。

源码已经上传资源。

继续阅读