背景
Mybatis的级联操作主要是针对一对多、多对一和多对多的情况而设定的。级联是在resultMap标签中配置的。级联并不是必须的,好处就是获取关联数据便捷,但如果级联过多会增加系统的复杂度,同时降低系统的性能。
一对多
一个人对应多件衣服为例
只查询一次
(1)先来看一下 标签中的属性:
property:对象属性的名称,对应一对多中一的字段名
ofType:指定的是映射到集合属性中bean的类型
column:所对应的外键字段名称
select:使用另一个查询封装的结果
xml文件
<!--一对多级联查询 resultMap-->
<resultMap id="oneToMoreResultMap" type="com.lks.bean.User">
<id column="id" property="id"></id>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="county" column="county"/>
<result property="date" column="date"/>
<!--对应一对多中一的字段名-->
<collection property="clothes" ofType="com.lks.bean.Clothe">
<id column="clothe_id" property="clotheId"></id>
<result column="clothe_color" property="clotheColor"></result>
<result column="user_id" property="userId"></result>
</collection>
</resultMap>
<select id="oneToMoreQuery" parameterType="int" resultMap="oneToMoreResultMap">
select id, name, age, county, date, clothe_id, clothe_color
FROM users join clothes on users.id = clothes.user_id
where users.id = #{id}
</select>
主要注意的是collection标签的property属性要对应一对多中一的字段名
mapper接口
public interface UserMapper {
List oneToMoreQuery(int id);
}
查询多次
当然也可以通过 < collection > 标签中 select 属性来执行另一个映射语句来返回预期的复杂类型结果
xml文件
<!--一对多级联查询 resultMap2-->
<resultMap id="oneToMoreResultMap2" type="com.lks.bean.User">
<id column="id" property="id"></id>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="county" column="county"/>
<result property="date" column="date"/>
<!--对应一对多中一的字段名-->
<collection property="clothes" ofType="com.lks.bean.Clothe" column="id" select="otherQuery">
<id column="clothe_id" property="clotheId"></id>
<result column="clothe_color" property="clotheColor"></result>
<result column="user_id" property="userId"></result>
</collection>
</resultMap>
<select id="otherQuery" parameterType="int" resultType="com.lks.bean.Clothe">
select clothe_id, clothe_color
FROM clothes
where user_id = #{user_id}
</select>
<select id="oneToMoreQuery2" parameterType="int" resultMap="oneToMoreResultMap2">
select id , name, age, county, date
FROM users
where id = #{id}
</select>
这个 < collection > 标签的select意思是:根据 oneToMoreQuery2 方法查询出的结果对象中的 id 属性当做参数,传递给 otherQuery 方法再次进行查询,实际上是执行了两次查询操作。
多对一
多件衣服对应一个人为例
先来看一下 < association > 标签中的属性:
property:对象属性的名称
javaType:对象属性的类型
column:所对应的外键字段名称
select:使用另一个查询封装的结果
在Clothe类中新增User属性
和一对多的场景类似,只不过这里是借助了association标签来进行关联:
xml文件:
<!--多对一级联查询 resultMap-->
<resultMap id="moreToOneResult" type="com.lks.bean.Clothe">
<id column="clothe_id" property="clotheId"></id>
<result column="clothe_color" property="clotheColor"></result>
<result column="user_id" property="userId"></result>
<!--对应多对一中多的字段名-->
<association property="user" javaType="com.lks.bean.User">
<id column="id" property="id"></id>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="county" column="county"/>
<result property="date" column="date"/>
</association>
</resultMap>
<select id="moreToOneQuery" parameterType="int" resultMap="moreToOneResult">
select id, name, age, county, date, clothe_id, clothe_color
FROM users join clothes on users.id = clothes.user_id
where clothes.user_id = #{id}
</select>
多对多
以用户和角色这个例子,一个用户可以属于多个角色,一个角色又可以分配多个用户,这就形成了一个多对多的关系,由于是多对多,就要使用到第三张表,这是一个关系表,用于记录两个表中的主键。
users表:
roles表:
user_role表:
查询user中的多角色
xml文件
<!--多对多级联查询 resultMap-->
<resultMap id="moreToMoreResultMap" type="com.lks.bean.User">
<id column="id" property="id"></id>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="county" column="county"/>
<result property="date" column="date"/>
<collection property="roles" ofType="com.lks.bean.Role" column="id">
<id column="role_id" property="roleId"></id>
<result column="role_name" property="roleName"></result>
</collection>
</resultMap>
<select id="moreToMoreQuery" parameterType="int" resultMap="moreToMoreResultMap">
select users.id, name, age, county, date, roles.role_id, role_name
FROM users
join user_role on users.id = user_role.user_id
join roles on roles.role_id = user_role.role_id
where users.id = #{id}
</select>
查询role中的多用户
xml文件
<!--多对多级联查询 resultMap-->
<resultMap id="moreToMoreResultMap" type="com.lks.bean.User">
<id column="id" property="id"></id>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="county" column="county"/>
<result property="date" column="date"/>
<collection property="roles" ofType="com.lks.bean.Role" column="id">
<id column="role_id" property="roleId"></id>
<result column="role_name" property="roleName"></result>
</collection>
</resultMap>
<select id="moreToMoreQuery" parameterType="int" resultMap="moreToMoreResultMap">
select users.id, name, age, county, date, roles.role_id, role_name
FROM users
join user_role on users.id = user_role.user_id
join roles on roles.role_id = user_role.role_id
where users.id = #{id}
</select>
其实多对多就是两个一对多组成的,一对多掌握了,多对多也就很容易上手了。
所以最重要的还是要掌握住一对多和多对一的写法,一法通则万法通,最基础的掌握住了,一对一和多对多也就不难理解了。另外主要好好理解 < collection > 和 < association > 标签,mybatis中级联查询的实现就是通过这两个标签实现的。