MyBatis之resultMap的作用和xml配置折腾

来源:互联网 发布:淘宝一元抢购在哪里? 编辑:程序博客网 时间:2024/05/22 06:45

简单的搭建。

MyBatis实战——前身iBatis、基础环境搭建和如何"钓鱼" 这篇写了基础的环境搭建和代码操作。

我这里是使用了xml加interface结合的方法进行操作。现有Employee类。如果是简单的select,可以看看下面简单的例子。

Employee.Java

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public class Employee {//省略get set 方法  
  2.     private int id;  
  3.     private String first_name;  
  4.     private String last_name;  
  5.     private int salary;  
  6. }  

EmployeeMapper.java

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.mybatis3.mappers;  
  2.   
  3. import model.Employee;  
  4.   
  5. public interface EmployeeMapper  
  6. {  
  7.     Employee findEmployeeById(Integer a);  
  8. }  

EmployeeMapper.xml(和EmployeeMapper.java位于同个package中

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>    
  2. <!DOCTYPE mapper    
  3.   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"    
  4.   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">    
  5. <mapper namespace="com.mybatis3.mappers.EmployeeMapper">    
  6.   <select id="findEmployeeById" resultType="model.Employee">    
  7.     select * from Employee where id = #{abc} <!-- 后面发现这个参数名这里填什么都无所谓,能映射到 -->  
  8.   </select>    
  9. </mapper>    

mybatis-config.xml的mappers映射改成:

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <mapper class="com.mybatis3.mappers.EmployeeMapper" />  

进行查询操作。

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public class Factory {    
  2.     public static void main(String[] args) {    
  3.         String configxml = "mybatis-config.xml";    
  4.         InputStream is = null;    
  5.         try {    
  6.             is = Resources.getResourceAsStream(configxml);    
  7.         } catch (IOException e) {    
  8.             e.printStackTrace();    
  9.         }    
  10.         SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);    
  11.         SqlSession s = sf.openSession();    
  12.         EmployeeMapper employeeMapper =  s.getMapper(EmployeeMapper.class);  
  13.         Employee e =  employeeMapper.findEmployeeById(47);  
  14.         System.out.println(e.getFirst_name());    
  15.         System.out.println(e.getLast_name());    
  16.         System.out.println(e.getSalary());   
  17.         s.close();    
  18.     }    
  19. }    

这是单表查询的时候,那么问题就来了。如果是多表复杂的查询。现在有了一张新表Employer,假如你是框架的设计者,会让Employee的字段全部丢到Employer中吗,显然不合适。


这是MyBatis提供了resultmap的方法。先看看单独一个类也可以使用resultmap进行映射。

Employer类

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public class Employer {  
  2.     private int id;//省略set get 方法  
  3.     private int employee_id;  
  4.     private String name;  
  5.     private Employee em;  
  6. }  


EmployerMapper.xml

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>    
  2. <!DOCTYPE mapper    
  3.   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"    
  4.   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  5.    
  6. <mapper namespace="com.mybatis3.mappers.EmployerMapper">  
  7.     <resultMap id="Employer" type="model.Employer">  
  8.         <id property="id" column="id" />  <!-- id相当于resultmap的引用的唯一标识-->  
  9.         <result property="name" column="name" />  <!-- property对应javabean的属性名,column对应数据库字段名 -->  
  10.         <result property="employee_id" column="employee_id" />  
  11.     </resultMap>  
  12.   
  13.     <select id="findEmployeeById" resultMap="Employer">  
  14.         select * from Employer where id = #{abc}  
  15.     </select>  
  16. </mapper>  


测试:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public class Factory {    
  2.     public static void main(String[] args) {    
  3.         String configxml = "mybatis-config.xml";    
  4.         InputStream is = null;    
  5.         try {    
  6.             is = Resources.getResourceAsStream(configxml);    
  7.         } catch (IOException e) {    
  8.             e.printStackTrace();    
  9.         }    
  10.         SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);    
  11.         SqlSession s = sf.openSession();    
  12.         EmployerMapper employerMapper =  s.getMapper(EmployerMapper.class);  
  13.         Employer e2 =  employerMapper.findEmployeeById(1);  
  14.         System.out.println(e2.getEmployee_id());  
  15.         System.out.println(e2.getName());  
  16.         s.close();    
  17.     }    
  18. }    


折腾resultMap的id,result属性:

接下来开始折腾了。将EmployerMapper.xml里面改成只剩:

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <resultMap id="Employer" type="model.Employer">  
  2. </resultMap>  
  3.   
  4. <select id="findEmployeeById" resultMap="Employer">  
  5.     select * from Employer where id = #{abc}  
  6. </select>  

发现还是能正常映射。但是如果改javabean的一个属性:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. private int employeeid;  
  2. public int getEmployeeid() {  
  3.     return employeeid;  
  4. }  
  5. public void setEmployeeid(int employee_id) {  
  6.     this.employeeid = employee_id;  
  7. }  

这样最后取值是取不到的,因为映射不到。那究竟是属性名还是通过getset方法的名字映射呢。再折腾:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. private int employeeid;  
  2. public int getEmployee_id() {  
  3.     return employeeid;  
  4. }  
  5. public void setEmployee_id(int employee_id) {  
  6.     this.employeeid = employee_id;  
  7. }  

employeeid属性名与数据库字段名不对应,但是get,set的方法名是和数据库字段名对应的。运行正常。

如果不想在配置这里瞎折腾,JavaBean字段名保持和数据库字段名是最好的选择。


折腾resultMap extends属性,表关联查询。

Employer.xml

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>    
  2. <!DOCTYPE mapper    
  3.   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"    
  4.   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  5.    
  6. <mapper namespace="com.mybatis3.mappers.EmployerMapper">  
  7.     <resultMap id="Employer" type="model.Employer">  
  8.     </resultMap>  
  9.     <resultMap type="model.Employer" id="EmployerWithEmployee"  
  10.         extends="Employer">  
  11.         <result property="em.id" column="id" />  
  12.         <result property="em.first_name" column="first_name" />  
  13.         <result property="em.last_name" column="last_name" />  
  14.         <result property="em.salary" column="salary" />  
  15.     </resultMap>  
  16.     <select id="findEmployeeById2" resultMap="EmployerWithEmployee">  
  17.         select employee_id,name,b.first_name,b.salary,b.last_name from Employer a  
  18.         left join Employee b on a.employee_id=b.id where a.id = #{abc}  
  19.     </select>  
  20. </mapper>  

测试:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);    
  2. SqlSession s = sf.openSession();    
  3. EmployerMapper employerMapper =  s.getMapper(EmployerMapper.class);  
  4. Employer e2 =  employerMapper.findEmployeeById2(1);  
  5. System.out.println(e2.getEmployee_id());  
  6. System.out.println(e2.getName());  
  7. System.out.println(e2.getEm().getFirst_name());  
  8. System.out.println(e2.getEm().getLast_name());  


注意这次的em不再是和上面第一个折腾的一样,是和方法名一致的。这次是和属性名一致。不然会报错。

而且MyBatis的关联查询就这么简单,还是一样的关联语句,只不过加了一些映射配置。


折腾association

extends拓展看起来挺好,但是讲到解耦的话,你extends出来是个不伦不类的东西。本身我就有Employee的存在。

所以,这时association出现了。

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <mapper namespace="com.mybatis3.mappers.EmployerMapper">  
  2.     <resultMap id="Employee" type="model.Employee">  
  3.         <id property="id" column="id" />  
  4.         <result property="first_name" column="first_name" />  
  5.         <result property="last_name" column="last_name" />  
  6.         <result property="salary" column="salary" />  
  7.     </resultMap>  
  8.   
  9.     <resultMap id="Employer" type="model.Employer">  
  10.         <id property="id" column="id" />  <!-- id相当于resultmap的引用的唯一标识-->  
  11.         <result property="name" column="name" />  <!-- property对应javabean的属性名,column对应数据库字段名 -->  
  12.         <result property="employee_id" column="employee_id" />  
  13.         <association property="em" resultMap="Employee" />  
  14.     </resultMap>  
  15.     <select id="findEmployeeById2" resultMap="Employer">  
  16.         select employee_id,name,b.first_name,b.salary,b.last_name from Employer a  
  17.         left join Employee b on a.employee_id=b.id where a.id = #{abc}  
  18.     </select>  
  19. </mapper>  

测试代码不变:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);    
  2. SqlSession s = sf.openSession();    
  3. EmployerMapper employerMapper =  s.getMapper(EmployerMapper.class);  
  4. Employer e2 =  employerMapper.findEmployeeById2(1);  
  5. System.out.println(e2.getEmployee_id());  
  6. System.out.println(e2.getName());  
  7. System.out.println(e2.getEme().getFirst_name());  
  8. System.out.println(e2.getEme().getLast_name());  
  9. s.close();    

但是不同于resultmap使用extends,result标签是不可少的,一旦少了,将获取不到其属性值。


经过上面种种折腾之后终于知道作者讲的作用是什么:最后就明白了书上所讲的ResultMap的作用,映射SQL选择声明的结果到JavaBean属性中。通过一对一和一对多associations可以将简单选择声明映射复杂的声明。

0 0