【MyBatis学习笔记】ResultMap、处理一对多的关系

自定义映射ResultMap

  • 若类的属性名(set、get) 名字段名(sql查出的列名)resultMap 不一致的解决办法

    • // java中:
      class User{
              id;
              username;
              password;
          }
      List<User> select(){
      		...
       mapper = sqlSessin.getMapper(..); 
         
       List<User> list = mapper.select ()
          '注意!resultMap只负责映射 返回的是你指定的type!'
      }
      
      // .xml中
      'id是resultMap的唯一标识,为了后边的映射'
      'type是映射返回的类型!'
      <resultMap id = "map" type = "xxx.User(目标类的全限名,也可以使用别名)">
          
      	<id property="id" column="id"> 'id标签 是主键专用的'
          <result property="username", column="user_Name"/>
          <result property="password", column="user_Password"/>
          
          '注意! property要写类的对应的名称 而column 则是查询出的列名'
          '注意!如果数据库的列名和类的名称一样 也必须要写!'
      </resultMap>
          
          
      <select id="select" resultMap = "map"> //这里是resultMap,不是resultType
       	select u.id, u.user_Name, 				u.user_Password from user u;
      </select>
      
           
      
    • 注意! property要写类的对应的名称 而column 则是查询出的列名
      注意!如果数据库的列名和类的名称一样 也必须要写!

处理一对多的关系

级联属性赋值

  • 用于解决一个实体类中的属性包含另一个实体类,也就是 一个类中的属性是一个实体类

  • 算了 说不太清!直接看例子

    • // .java中:
      class Dep{	//部门表
          did;
          depName;
          location;
      }
      class User{	//员工表
              id;
              username;
              password;
          	Dep dep;'多了个部门信息对象'
          }
      List<User> select(){
      		...
       mapper = sqlSessin.getMapper(..); 
       List<User> list = mapper.select ()
          '注意!resultMap只负责映射 返回的是你指定的type!'
      }
      ----------------------------------
      // .xml中
      'id是resultMap的唯一标识,为了后边的映射'
      'type是映射返回的类型!'
      <resultMap id = "map" type = "xxx.User">
          
      	<id property="id" column="id"> 'id标签 是主键专用的'
          <result property="username", column="user_Name"/>
          <result property="password", column="user_Password"/>
          
          <result property="dep.did" , column="did"/>
          <result property="dep.depName", column="dep_Name"/>
          <result property="dep.location", column="location"/>
          
          '通过级联属性赋值的方式 可以自动填充user中的dep对象属性值'
      </resultMap>
          
          
      <select id="select" resultMap = "map"> 
       	select 
       		u.id, u.user_Name, u.user_Password ,
       		d.did, d.dep_Name, d.location
       	from user u Left join dep d 
       		  on u.did = d.did;
      </select>
      
           
      
      
    • 大家会发现,级联赋值看着好混 没有层次感,不要着急!下面有新的方法!

Association

级联属性赋值 更加优化

  • 使封装的实体类 表示更具有层次感 逻辑感!

    • // .java中:
      class Dep{	//部门表
          did;
          depName;
          location;
      }
      class User{	//员工表
              id;
              username;
              password;
          	Dep dep;'多了个部门信息对象'
          }
      List<User> select(){
      		...
       mapper = sqlSessin.getMapper(..); 
       List<User> list = mapper.select()
      }
      ----------------------------------
      // .xml中
      
      <resultMap id = "map" type = "xxx.User">
      	<id property="id" column="id">
          <result property="username", column="user_Name"/>
          <result property="password", column="user_Password"/>
          
          
        'property是User中要封装参数名, javaType是对应的封装类型'
        <association property="dep" javaType="xxx.dep">
        	<id	property="did",  column="did"/> 'id标签 是主键专用的'
          <result property="depName", column="dep_Name"/>
          <result property="location", column="location"/>
        </association>
        
          '通过association的方式 使得封装更有层次感 可读性更高'
      </resultMap>
          
          
      <select id="select" resultMap = "map"> 
       	select 
       		u.id, u.user_Name, u.user_Password ,
       		d.did, d.dep_Name, d.location
       	from user u 
       		Left join dep d 
       		  on u.did = d.did;
      </select>
      
           
      
    • 大家有没有想过,如果属性是一个集合呢?来,下面的collection为你解决!

Collection

  • 专门来处理集合映射(一对多)

  • // .java中:
    class Dep{	//部门表
        did;
        depName;
        location;
        List<User> users; //此部门中的员工信息
    }
    class User{	//员工表
            id;
            username;
            password;
        	depId;
        }
    List<User> select(){
    		...
     mapper = sqlSessin.getMapper(..); 
     List<Dep> deps = mapper.select()
    }
    ----------------------------------
    // .xml中
    
    <resultMap id = "map" type = "xxx.Dep">
    	<id property="did" column="did">
        <result property="depName", column="dep_Name"/>
        <result property="location", column="location"/>
        
        'property为属性名称 oftype为要封装的类型(list集合中的泛型)'
        <collection property="users" ofType="xxx.User">
        	<id property="id" column="id">
        	<result property="username", column="user_Name"/>
        	<result property="password", column="user_Password"/>
        	<result property="depId", column="did"/>
        </collection>
      
    </resultMap>
        
        
    <select id="select" resultMap = "map"> 
     	select 
     		u.id, u.user_Name, u.user_Password ,
     		d.did, d.dep_Name, d.location
     	from  dep d 
     		Left join user u 
     		  on d.did = u.did;
    </select>
    
         
    

分布查询

注:这分布查询 直接摘抄了尚硅谷的笔记

  1. 查询部门信息
/**
 * 通过分步查询,查询部门及对应的所有员工信息
 * 分步查询第一步:查询部门信息
 * @param did 
 * @return com.atguigu.mybatis.pojo.Dept
 * @date 2022/2/27 22:04
 */
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
	<id property="did" column="did"></id>
	<result property="deptName" column="dept_name"></result>
	<collection property="emps"
				select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
				column="did"></collection>
</resultMap>
<!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap">
	select * from t_dept where did = #{did}
</select>
  1. 根据部门id查询部门中的所有员工
/**
 * 通过分步查询,查询部门及对应的所有员工信息
 * 分步查询第二步:根据部门id查询部门中的所有员工
 * @param did
 * @return java.util.List<com.atguigu.mybatis.pojo.Emp>
 * @date 2022/2/27 22:10
 */
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
	select * from t_emp where did = #{did}
</select>

延迟加载

  • 分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
    • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
    • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载
  • 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加载)|eager(立即加载)”
<settings>
	<!--开启延迟加载-->
	<setting name="lazyLoadingEnabled" value="true"/>
</settings>
@Test
public void getEmpAndDeptByStepOne() {
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	Emp emp = mapper.getEmpAndDeptByStepOne(1);
	System.out.println(emp.getEmpName());
}
  • 关闭延迟加载,两条SQL语句都运行了!
  • 开启延迟加载,只运行获取emp的SQL语句
@Test
public void getEmpAndDeptByStepOne() {
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	Emp emp = mapper.getEmpAndDeptByStepOne(1);
	System.out.println(emp.getEmpName());
	System.out.println("----------------");
	System.out.println(emp.getDept());
}
  • 开启后,需要用到查询dept的时候才会调用相应的SQL语句
  • fetchType:当开启了全局的延迟加载之后,可以通过该属性手动控制延迟加载的效果,fetchType=“lazy(延迟加载)|eager(立即加载)”
```xml
<resultMap id="empAndDeptByStepResultMap" type="Emp">
	<id property="eid" column="eid"></id>
	<result property="empName" column="emp_name"></result>
	<result property="age" column="age"></result>
	<result property="sex" column="sex"></result>
	<result property="email" column="email"></result>
	<association property="dept"
				 select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
				 column="did"
				 fetchType="lazy"></association>
</resultMap>
```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值