【mybatis】关联查询——mybatis一对多两种方式实现详解

本文深入探讨MyBatis框架中关联查询的两种方式:嵌套查询和嵌套结果映射。通过具体示例,详细解释了如何配置mapper.xml文件进行一对多和一对一的关联查询,包括使用collection和association标签,以及如何指定SQL语句和映射实体类属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

此种方式需要查询数据库两次,发出两次sql语句,一次是查询tbl_phone表,一次是查询tbl_person表,但是数据库返回的信息没有冗余,mapper.xml配置和测试代码如下。

<?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="cn.wxy.dao.PersonDao">
    <resultMap type="Phone" id="selectPhomap">
        <id property="id" column="id"/>
        <result property="phoneNum" column="phoneNum"/>
        <collection property="persons" ofType="Person" select="selectPer" column="id">
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="password" column="password"/>
            <result property="gender" column="gender"/>
            <result property="age" column="age"/>
            <result property="phoneID" column="phoneID"/>
        </collection>
    </resultMap>
    <select id="select" parameterType="int" resultMap="selectPhomap">
        select * from tbl_phone where id=#{id}
    </select>
    <select id="selectPer" parameterType="int" resultType="Person">
        select * from tbl_person where phoneID=#{phoneID}
    </select>
</mapper>


        用直白的话来描述此种方式,在调用mapper接口中的select方法,先走语句“select * from tbl_phone where id=#{id}”,从数据库中拿到返回数据之后,开始做返回值映射,此时的返回值映射对象是一个resultMap(id:selectPhomap),该resultMap实际上是一个Phone实例,因此在开始做映射的时候,id和phoenNum因为属性名和数据库返回值一致完成映射,但是到了persons属性的时候,发现他是一个collection集合对象,里面存放的是Person实例,那怎么获取里面的数据?看collection标签的属性,他需要关联一个查询操作select="selectPer"获取其数据,即通过select * from tbl_person where phoneID=#{phoneID}获取collection中的数据,select="selectPer"操作需要传入数据,传入的数据column="id"即是第一次查询中返回的phone id,这个在这里显得不明显,在第二种方式中会更加的明显,这里也是mybatis关联查询的核心点,最后一步,就是将第二次查询出来的数据映射到collection中。详细过程,通过打印日志也可窥见一斑
 

 


聚集元素用来处理“一对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList);列表中对象的类型ofType(Java实体类);对应的数据库表的列名称;
不同情况需要告诉MyBatis 如何加载一个聚集。MyBatis 可以用两种方式加载:

1. select: 执行一个其它映射的SQL 语句返回一个Java实体类型。较灵活但会将执行多次嵌套的SQL语句。
2. resultMap: 使用一个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型。

两种加载方式格式如下:

1.集合的嵌套查询(select)

<collection property="Java属性名" ofType="另一Java类名" javaType="ArrayList" column="关联主键ID(用于嵌套查询SQL语句传入参数,多个用逗号分开)" select="另一个select映射SQL的ID"/>

<select parameterType="int" resultType="另一Java类名" id="另一个select映射SQL的ID">

SQL语句

<select>

注意:column属性的值必须与相应的SQL查询语句中的列名相同。MyBatis会将第一条SQL语句查询出来的该列的值用于所嵌套的SQL映射语句的入参。因第一条SQL语句查询出来的每个该列的值都将用于执行另一个SQL语句,所以嵌套的SQL语句将被多次执行。

2.集合的嵌套结果(resultMap)

<collection property="Java属性名" ofType="另一Java类名" javaType="ArrayList" resultMap="另一个resultMap的ID"/>

<resultMap="另一个resultMap的ID" type="另一Java类名">

<id property="id" column="关联主键ID"/>

........

</resultMap>

注意:column属性的值必须与相应的SQL查询语句的列名一样。

 


<resultMap id="roleDetailMap" type="cn.piesat.entity.DataRole" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="name" property="name" jdbcType="VARCHAR" />
    <result column="remark" property="remark" jdbcType="VARCHAR" />
    <collection property="privilege"  column="id"  ofType="cn.piesat.entity.Privilege" select="selectPrivileges" >			
		 <id column="id" property="id" jdbcType="INTEGER" />
         <result column="variable" property="variable" jdbcType="VARCHAR" />
         <result column="name" property="name" jdbcType="VARCHAR" />
         <result column="remark" property="remark" jdbcType="VARCHAR" />
         <result column="device_id" property="deviceId" jdbcType="VARCHAR" />
		</collection> 
  </resultMap>
  
 <select id="selectPrivileges" parameterType="String" resultType="cn.piesat.entity.Privilege">
		select id,name,variable,remark ,device_id deviceId from privilege where id in (select priv_id from role_privilege where role_id = #{id})
	</select>
	
	 <select id="queryRoleDetail" resultMap="roleDetailMap" parameterType="java.lang.String" >
    select 
    <include refid="Base_Column_List" />
    from data_role
    where id = #{id}
  </select>

一对一关联查询

<!-- namespace命名空间,唯一标识。一般指定为自定义的接口文件,下面相当于这个接口的实现类 -->
<mapper namespace="com.mybatis.mapper.EmployeeMapperPlus">
    <resultMap type="com.mybatis.domain.Employee" id="myEmpByStep">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
        <result column="email" property="email"/>
        <!-- 使用select属性指定第二步调用的方法,并通过column指定传递的参数值,这个值是第一步的查询的数据 -->
        <association property="dept" 
            select="com.mybatis.mapper.DepartmentMapper.getDeptById"
            column="dept_id">
        </association>
    </resultMap>
    <!-- 第一步值只查询tbl_employee表 -->
    <select id="getEmpAndDeptByStep" resultMap="myEmpByStep">
        select id,last_name,gender,email,dept_id
         from tbl_employee
         where id = #{id}
    </select>
</mapper>
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值