SSM项目从零开始到入门025-mybatis的resultMap自定义高级映射规则 SSM项目从零开始到入门025-mybatis的resultMap自定义高级映射规则

SSM项目从零开始到入门025-mybatis的resultMap自定义高级映射规则

       通过前面的了解,我们指定查询结果的返回值类型都是通过使用select元素的resultType属性来指定,来让MyBatis自动将查询结果集封装成我们希望的类型进行返回。
     resultType属性非常有用,但在返回结果类型比较复杂的情况下却无能为力,为此,MyBatis在select元素中还为我们提供了另外一个resultMap属性,用于引用一个使用<resultMap/>元素定义好的自定义结果集映射规则。

    <resultMap/>算是MyBatis中最重要、最强大的元素了,它可以让你比使用JDBC调用结果集省掉90%的代码,也可以让你做许多JDBC不支持的事。 事实上,编写类似的对复杂语句联合映射的代码也许会需要上千行。resultMap的设计就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们的关系。

resultMap子元素:

[html] view plain copy
  1. <!---用来将查询结果作为参数注入到实例的构造方法中->  
  2. <constructor>      
  3.    <!--标记结果作为 ID-->  
  4.    <idArg />       
  5.    <!--标记结果作为普通参数-->  
  6.    <arg />          
  7. </constructor>    
  8. <!--一个ID结果,标记结果作为 ID-->  
  9. <id/>           
  10. <!--一个普通结果,JavaBean的普通属性或字段-->  
  11. <result/>        
  12. <!--关联其他的对象-->  
  13. <association></association>       
  14. <!--关联其他的对象集合-->   
  15. <collection></collection>         
  16. <!--鉴别器,根据结果值进行判断,决定如何映射-->     
  17. <discriminator>               
  18.     <!--结果值的一种情况,将对应一种映射规则-->  
  19.     <case></case>      
  20. </discriminator>  
     在一个<resultMap/>元素中,这些子元素出现的先后顺序是有严格规定的,它们从前到后依次是:constructor-->id --> result--> association-->collection -->discriminator。
id & result

     <id/>和<result/>是resultMap中最基本的映射内容,它们都可以将查询结果中一个单独列的值映射为返回结果对象中的简单数据类型(字符串,整型,双精度浮点数,日期等)的单独属性或字段。这两者之间的唯一不同是id 表示的结果将是当比较对象实例时用到的标识属性。这帮助来改进整体表现,特别是缓存和嵌入结果映射(也就是联合映射) 。

     

[html] view plain copy
  1. <!-- 返回javaBean对象 -->    
  2. <resultMap type="User" id="userResultMap">    
  3.     <id column="USER_ID" property="userId" />    
  4.     <result column="USER_NAME" property="userName" />    
  5.     <result column="USER_PASS" property="passWord" />    
  6.     <result column="USER_GENDER" property="gender" />     
  7. </resultMap>  
[html] view plain copy
  1. <!-- 返回Map对象 -->    
  2. <resultMap type="map" id="userResultMap">    
  3.     <id column="USER_ID" property="userId" javaType="long"/>    
  4.     <result column="USER_NAME" property="userName" javaType="string"/>    
  5.     <result column="USER_PASS" property="passWord" javaType="string"/>    
  6.     <result column="USER_GENDER" property="gender" javaType="string"/>    
  7. </resultMap>  

<id/>和<result/>都支持以下几个属性:

属性 描述
column 从数据库中查询到的结果集的列名或列别名
property 将 column属性指定的列结果映射到对象的哪个属性
javaType 列结果在对象中所对应的Java数据类型,返回类型为Map时需指定
jdbcType 列结果在数据库中所支持的JDBC 类型
typeHandler 所使用的类型处理器

为了未来的参考,MyBatis 通过包含的 jdbcType 枚举型,支持下面的 JDBC 类型。

BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINED
TINYINT REAL VARCHAR BINARY BLOB NVARCHAR
SMALLINT DOUBLE LONGVARCHAR VARBINARY CLOB NCHAR
INTEGER NUMERIC DATE LONGVARBINARY BOOLEAN NCLOB
BIGINT DECIMAL TIME NULL CURSOR ARRAY


constructor


       使用<constructor/>元素可以在对象实例化时,将查询到结果集作为参数注入到实例的构造方法中,以实现对实例化对象的特殊处理。
      例如,为了防止由于数据库user表中的年龄字段长期未更新,而导致查询出来的年龄信息不准确,我们希望查询user信息时根据用户的生日计算出用户的年龄,而不再直接从数据库中获取用户的年龄信息。
首先在用户实体类User.java中增加如下构造方法:
     
[java] view plain copy
  1. private static final SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");    
  2. public User(Long userId, Date birthday) {    
  3.     super();    
  4.     this.userId = userId;    
  5.     if (null != birthday) {   
  6.         this.birthday = birthday;    
  7.         int startYear = Integer.parseInt(yearFormat.format(birthday));    
  8.         int nowYear = Integer.parseInt(yearFormat.format(new Date()));    
  9.         this.age = nowYear - startYear;    
  10.     }    
  11. }    

相应的Mapper配置如下:

[html] view plain copy
  1. <resultMap type="User" id="userResultMap">    
  2.     <constructor>    
  3.         <idArg column="USER_ID" javaType="java.lang.Long" />    
  4.         <arg column="USER_BIRTHDAY" javaType="java.util.Date" />    
  5.     </constructor>    
  6.     <id column="USER_ID" property="userId" />    
  7.     <result column="USER_NAME" property="userName" />    
  8.     <result column="PASS_WORD" property="userGender" />    
  9. </resultMap>    
  10. <select id="selectUserById" resultMap="userResultMap">    
  11.     select * from  t_user where  USER_ID =  #{userId}    
  12. </select>    
     <constructor/>元素的<idArg/>和<arg/>除了支持示例中的column和javaType属性,还支持以下几个属性:jdbcType、typeHandler、select、resultMap、name,其中的name属性从3.4.3版本起开始引入,用来指定该在构造方法中形参的名字。

注意:使用<constructor/>元素在构造方法中初始化的参数若使用resultMap的其他子元素进行映射,则构造方法为对象实例赋予的属性值将被覆盖。

association


<association/>元素用于处理查询结果中关联其他对象的情况。

比如:一个用户属于一个部门,我们在查询一个用户的信息时,想要把他所在的部门也一并查出。

[java] view plain copy
  1. public class User{    
  2.     
  3.     private Long userId;       //用户id  
  4.     private String userName;   //用户名称  
  5.     ....                       //省略一些属性  
  6.     private Dept dept;         //所属部门  
  7.         
  8.     //此处省略get和set方法    
  9.     
  10. }  

MyBatis提供了两种不同的方式用来处理这种对象关联查询:嵌套查询和嵌套结果。


嵌套查询

所谓嵌套查询,指的是通过执行另外一个 SQL 映射语句来返回所关联的对象类型。

<association/>元素可以通过columnPrefix属性可以去除查询结果内列名的指定前缀。

[html] view plain copy
  1. <resultMap type="User" id="userResultMap">    
  2.     <id column="USER_ID" property="userId" />    
  3.     <result column="USER_NAME" property="userName" />    
  4.     <association column="DEPT_ID" property="dept" select="selectDeptById" javaType="Dept" />    
  5. </resultMap>    
  6. <select id="selectUserById" resultMap="userResultMap">    
  7.     select * from  t_user where  USER_ID =  #{userId}    
  8. </select>    
  9. <resultMap type="Dept" id="deptResultMap">    
  10.     <id column="DEPT_ID" property="deptId" />    
  11.     <result column="DEPT_NAME" property="deptName" />    
  12. </resultMap>    
  13. <select id="selectDeptById" resultMap="deptResultMap">    
  14.     select * from  t_dept  where  DEPT_ID =  #{deptId}    
  15. </select>  

嵌套结果


所谓嵌套结果,指的是通过联表查询将所需的所有字段内容先查询出来,再通过级联属性映射来创建复杂类型的结果对象。


[html] view plain copy
  1. <resultMap type="User" id="userResultMap">    
  2.     <id column="USER_ID" property="userId" />    
  3.     <result column="USER_NAME" property="userName" />    
  4.     <result column="DEPT_ID" property="dept.deptId" />    
  5.     <result column="DEPT_NAME" property="dept.deptName" />    
  6. </resultMap>    
  7. <sql id="userAndDeptFields">    
  8.     u.USER_ID   AS USER_ID,    
  9.     u.USER_NAME AS USER_NAME,    
  10.     d.DEPT_ID   AS DEPT_ID,    
  11.     d.DEPT_NAME AS DEPT_NAME    
  12. </sql>    
  13. <select id="selectUserById" resultMap="userResultMap">    
  14.     SELECT    
  15.     <include refid="userAndDeptFields"></include>    
  16.     FROM  t_user u  LEFT OUTER JOIN  t_dept d  ON u.DEPT_ID = d.DEPT_ID    
  17.     WHERE    
  18.     u.USER_ID = #{userId}    
  19. </select>   

此时的resultMap还可以写为如下两种形式。

[html] view plain copy
  1. <resultMap type="User" id="userResultMap">    
  2.     <id column="USER_ID" property="userId" />    
  3.     <result column="USER_NAME" property="userName" />    
  4.     <association property="dept" javaType="Dept">    
  5.         <id column="DEPT_ID" property="deptId" />    
  6.         <result column="DEPT_NAME" property="deptName" />    
  7.     </association>    
  8. </resultMap>   
[html] view plain copy
  1. <resultMap type="User" id="userResultMap">    
  2.     <id column="USER_ID" property="userId" />    
  3.     <result column="USER_NAME" property="userName" />    
  4.     <association property="dept" resultMap="deptResultMap">  </association>    
  5. </resultMap>    
  6. <resultMap type="Dept" id="deptResultMap">    
  7.     <id column="DEPT_ID" property="deptId" />    
  8.     <result column="DEPT_NAME" property="deptName" />    
  9. </resultMap>   

collection


<collection/>元素用于处理查询结果中关联其他对象集合的情况,比如:一个部门包含多个员工,我们在查询一个部门的信息时,想要把这个部门里的员工集合也一并查出。

部门实体:

[html] view plain copy
  1. public class Dept{    
  2.     private Long deptId;       //部门id  
  3.     private String deptName;   //部门名称  
  4.     ...  
  5.     private List<User> users;  //部门下用户集合  
  6.     //此处省略get和set方法    
  7. }    

嵌套查询

[html] view plain copy
  1. <resultMap type="Dept" id="deptResultMap">    
  2.     <id column="DEPT_ID" property="deptId" />    
  3.     <result column="DEPT_NAME" property="deptName" />    
  4.     <collection column="DEPT_ID" property="users" javaType="list"  select="userListByClass">  </collection>    
  5. </resultMap>    
  6.   
  7. <resultMap type="User" id="userResultMap">    
  8.     <id column="USER_ID" property="userId" />    
  9.     <result column="USER_NAME" property="userName" />    
  10. </resultMap>    
  11.   
  12. <select id="selectDeptById" resultMap="deptResultMap">    
  13.     select * from  t_dept  where DEPT_ID =  #{deptId}    
  14. </select>    
  15.   
  16. <select id="userListByClass" parameterType="long"  resultMap="userResultMap">    
  17.     select * from  t_user   where   DEPT_ID = #{userId}    
  18. </select>  

嵌套结果

[html] view plain copy
  1. <resultMap type="Dept" id="deptResultMap">    
  2.     <id column="DEPT_ID" property="deptId" />    
  3.     <result column="DEPT_NAME" property="deptName" />    
  4.     <collection column="DEPT_ID" property="users" javaType="list"  ofType="User">    
  5.         <id column="User_ID" property="userId" />    
  6.         <result column="USER_NAME" property="userName" />    
  7.     </collection>    
  8. </resultMap>    
  9. <sql id="deptAndUsersFields">    
  10.     d.DEPT_ID   AS DEPT_ID,    
  11.     d.DEPT_NAME AS DEPT_NAME,    
  12.     u.USER_ID   AS USER_ID,    
  13.     u.USER_NAME AS USER_NAME    
  14. </sql>    
  15. <select id="selectDeptById" parameterType="long" resultMap="deptResultMap">    
  16.     SELECT    
  17.     <include refid="deptAndUsersFields"></include>    
  18.     FROM  t_dept d LEFT JOIN t_user u ON d.DEPT_ID = u.DEPT_ID    
  19.     WHERE    
  20.     d.DEPT_ID = #{deptId}    
  21. </select>   

此时的resultMap也可以写为如下形式。

[html] view plain copy
  1. <resultMap type="Dept" id="deptResultMap">    
  2.     <id column="DEPT_ID" property="deptId" />    
  3.     <result column="DEPT_NAME" property="deptName" />    
  4.     <collection property="users" javaType="list" ofType="User" resultMap="userResultMap">  </collection>    
  5. </resultMap>    
  6. <resultMap type="User" id="userResultMap">    
  7.     <id column="USER_ID" property="userId" />    
  8.     <result column="USER_NAME" property="userName" />    
  9. </resultMap>   

discriminator


<discriminator/>元素很像Java语言中的switch 语句,允许用户根据查询结果中指定字段的不同取值来执行不同的映射规则,比如:在查询一个部门的员工信息时,如果员工是性别为男则将其年龄信息一并查出,如果学生为女性则不查询其年龄信息而是将部门信息一并查出。

[html] view plain copy
  1. <resultMap type="User" id="usersResultMap">    
  2.     <discriminator column="USER_GENDER" javaType="string">    
  3.         <case value="男" resultMap="maleResultMap"/>    
  4.         <case value="女" resultMap="femaleResultMap"/>    
  5.     </discriminator>    
  6. </resultMap>    
  7. <resultMap type="User" id="maleResultMap">    
  8.     <id column="USER_ID" property="userId" />    
  9.     <result column="USER_NAME" property="userName" />    
  10.     <result column="USER_AGE" property="userAge" />    
  11. </resultMap>    
  12. <resultMap type="User" id="femaleResultMap">    
  13.     <id column="USER_ID" property="userId" />    
  14.     <result column="USER_NAME" property="userName" />    
  15.     <association column="DEPT_ID" property="dept"  javaType="Dept">    
  16.         <id column="DEPT_ID" property="deptId" />    
  17.         <result column="DEPT_NAME" property="deptName" />    
  18.     </association>    
  19. </resultMap>   

此时的resultMap也可以写为如下形式。

[html] view plain copy
  1. <resultMap type="User" id="usersResultMap">    
  2.     <id column="USER_ID" property="userId" />    
  3.     <result column="USER_NAME" property="userName" />    
  4.     <discriminator column="USER_GENDER" javaType="string">    
  5.         <case value="男" resultType="User">    
  6.             <result column="USER_AGE" property="userAge" />    
  7.         </case>    
  8.         <case value="女" resultType="User">    
  9.             <association column="DEPT_ID" property="userDept"  javaType="Dept">    
  10.                 <id column="DEPT_ID" property="deptId" />    
  11.                 <result column="DEPT_NAME" property="deptName" />    
  12.             </association>    
  13.         </case>    
  14.     </discriminator>    
  15. </resultMap>   

猜你喜欢

转载自blog.csdn.net/zxl2016/article/details/80696805
今日推荐