【笔记】Mybatis高级查询(一)--使用自动映射处理一对一关系

【笔记】Mybatis高级查询(准备)
【笔记】Mybatis高级查询(二)–使用resultMap配置一对一映射
【笔记】Mybatis高级查询(三)–使用标签实现嵌套查询及延迟加载
【笔记】Mybatis高级查询(四)–使用resultMap的标签实现一对多和多对多查询
【笔记】Mybatis高级查询(五)–使用resultMap的进行嵌套查询及延迟加载
【笔记】Mybatis高级查询(小结)–嵌套查询及延迟加载
【笔记】Mybatis高级查询(六)–鉴别器discrimiator的使用
【笔记】Mybatis高级查询(七)–存储过程调用
【笔记】Mybatis高级查询(八)–枚举处理器的使用
【笔记】Mybatis高级查询(九)–Mybatis代码生成器的使用
【笔记】Mybatis高级查询(十)–Mybatis缓存使用

假设在RBAC权限系统中,一个用户只能有一个角色,那么就是一对一关系了。一对一映射因为不需要考虑是否存在重复数据,用起来简单,所以可以直接使用Mybatis的自动映射。

以下例子为使用自动映射实现在查询用户信息的同时获取用户的角色信息。

  1. 在SysUser类中增加SysRole的属性,代码如下:
    public class SysUser {
        // 其它原有属性
        
        /**
         * 假设一个用户只有一个角色(使用自动映射处理一对一关系)
         */
        private SysRole role;
    
        public SysRole getRole() {
    		return role;
    	}
    
    	public void setRole(SysRole role) {
    		this.role = role;
    	}
    }
    
  2. 在映射文件SysUserMapper.xml增加selectUserAndRoleById方法,如下:
      
      
    
  3. 在SysUserMapper接口中增加selectUserAndRoleById方法,如下:
    	/**
         * 假设一个用户只有一个角色(使用自动映射处理一对一关系)
         * @param id
         * @return
         */
        SysUser selectUserAndRoleById(Long id);
    
  4. 在UserMaperTest类中增加对应的测试方法,如下:
    	@Test
    	public void testSelectUserAndRoleById() {
    		// 获取SqlSession
    		SqlSession sqlSession = openSession();
    		try {
    			// 获取SysUserMapper接口
    			SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class);
    			
    			// 调用selectUserAndRoleById方法
    			SysUser user = userMapper.selectUserAndRoleById(1001L);
    			
    			// user不为空
    			Assert.assertNotNull(user);
    			
    			System.out.println(user.getRole());
    			
    			// role不为空
    			Assert.assertNotNull(user.getRole());
    			
    			System.out.println();
    		} finally {
    			sqlSession.close();
    		}
    	}
    
  5. 运行结果
    [ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById] - ==>  Preparing: select u.id, u.user_name, u.user_password, u.user_email, u.create_time, u.user_info, u.head_img, r.id "role.id", r.role_name "role.roleName", r.enabled "role.enabled", r.create_by "role.createBy", r.create_time "role.createTime" from sys_user u inner join sys_user_role ur on u.id = ur.user_id inner join sys_role r on ur.role_id = r.id where u.id = ? 
    [ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById] - ==> Parameters: 1001(Long)
    [ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById] - <==    Columns: id, user_name, user_password, user_email, create_time, user_info, head_img, role.id, role.roleName, role.enabled, role.createBy, role.createTime
    [ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById] - <==        Row: 1001, test, 123456, [email protected], 2018-10-02 17:17:11.0, <>, <>, 2, 普通用户, 0, 1, 2018-10-01 18:27:37.0
    [ex.mybatis.rbac.mapper.SysUserMapper.selectUserAndRoleById] - <==      Total: 1
    
  6. Mybatis自动映射原理

自动映射是通过别名让Mybatis自动将值匹配到对应的字段上,如果是简单的映射如user_name则对应userName。如果是多层嵌套,如将role.role_name映射到role.roleName上。Mybatis会先查找role属性,如果存在就创建role对象,然后在role对象中继续查找roleName。将role_name的值绑定到role对象的roleName上。

源码处理流程为:
第一步:在org.apache.ibatis.reflection.Reflector的addGetMethods、addSetMethods、addFields方法中把类属性的字段名,setter和getter方法进行处理,保存属性的类型到一个setTypes和getTypes的map中,key为属性名或setter、getter后面字段。如SysUser类经过处理后得到的setTypes和getTypes如下:

setTypes:{userInfo=class java.lang.String, userPassword=class java.lang.String, role=class ex.mybatis.rbac.model.SysRole, headImg=class [B, createTime=class java.util.Date, userEmail=class java.lang.String, id=class java.lang.Long, userName=class java.lang.String}

getTypes:{userInfo=class java.lang.String, userPassword=class java.lang.String, role=class ex.mybatis.rbac.model.SysRole, headImg=class [B, createTime=class java.util.Date, userEmail=class java.lang.String, id=class java.lang.Long, userName=class java.lang.String}

第二步:通过org.apache.ibatis.executor.resultset.DefaultResultSetHandler.applyAutomaticMappings的setValue方法利用反射获取类的setter方法进行赋值。

你可能感兴趣的:(mybatis)