MyBatis之resultMap的作用和xml配置折騰
阿新 • • 發佈:2019-02-06
簡單的搭建。
我這裡是使用了xml加interface結合的方法進行操作。現有Employee類。如果是簡單的select,可以看看下面簡單的例子。
Employee.java
public class Employee {//省略get set 方法
private int id;
private String first_name;
private String last_name;
private int salary;
}
EmployeeMapper.java
package com.mybatis3.mappers; import model.Employee; public interface EmployeeMapper { Employee findEmployeeById(Integer a); }
EmployeeMapper.xml(和EmployeeMapper.java位於同個package中
<?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="com.mybatis3.mappers.EmployeeMapper"> <select id="findEmployeeById" resultType="model.Employee"> select * from Employee where id = #{abc} <!-- 後面發現這個引數名這裡填什麼都無所謂,能對映到 --> </select> </mapper>
mybatis-config.xml的mappers對映改成:
<mapper class="com.mybatis3.mappers.EmployeeMapper" />
進行查詢操作。
public class Factory { public static void main(String[] args) { String configxml = "mybatis-config.xml"; InputStream is = null; try { is = Resources.getResourceAsStream(configxml); } catch (IOException e) { e.printStackTrace(); } SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is); SqlSession s = sf.openSession(); EmployeeMapper employeeMapper = s.getMapper(EmployeeMapper.class); Employee e = employeeMapper.findEmployeeById(47); System.out.println(e.getFirst_name()); System.out.println(e.getLast_name()); System.out.println(e.getSalary()); s.close(); } }
這是單表查詢的時候,那麼問題就來了。如果是多表複雜的查詢。現在有了一張新表Employer,假如你是框架的設計者,會讓Employee的欄位全部丟到Employer中嗎,顯然不合適。
這是MyBatis提供了resultmap的方法。先看看單獨一個類也可以使用resultmap進行對映。
Employer類
public class Employer {
private int id;//省略set get 方法
private int employee_id;
private String name;
private Employee em;
}
EmployerMapper.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="com.mybatis3.mappers.EmployerMapper">
<resultMap id="Employer" type="model.Employer">
<id property="id" column="id" /> <!-- id相當於resultmap的引用的唯一標識-->
<result property="name" column="name" /> <!-- property對應javabean的屬性名,column對應資料庫欄位名 -->
<result property="employee_id" column="employee_id" />
</resultMap>
<select id="findEmployeeById" resultMap="Employer">
select * from Employer where id = #{abc}
</select>
</mapper>
測試:
public class Factory {
public static void main(String[] args) {
String configxml = "mybatis-config.xml";
InputStream is = null;
try {
is = Resources.getResourceAsStream(configxml);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);
SqlSession s = sf.openSession();
EmployerMapper employerMapper = s.getMapper(EmployerMapper.class);
Employer e2 = employerMapper.findEmployeeById(1);
System.out.println(e2.getEmployee_id());
System.out.println(e2.getName());
s.close();
}
}
折騰resultMap的id,result屬性:
接下來開始折騰了。將EmployerMapper.xml裡面改成只剩:
<resultMap id="Employer" type="model.Employer">
</resultMap>
<select id="findEmployeeById" resultMap="Employer">
select * from Employer where id = #{abc}
</select>
發現還是能正常對映。但是如果改javabean的一個屬性:
private int employeeid;
public int getEmployeeid() {
return employeeid;
}
public void setEmployeeid(int employee_id) {
this.employeeid = employee_id;
}
這樣最後取值是取不到的,因為對映不到。那究竟是屬性名還是通過getset方法的名字對映呢。再折騰:
private int employeeid;
public int getEmployee_id() {
return employeeid;
}
public void setEmployee_id(int employee_id) {
this.employeeid = employee_id;
}
employeeid屬性名與資料庫欄位名不對應,但是get,set的方法名是和資料庫欄位名對應的。執行正常。
如果不想在配置這裡瞎折騰,JavaBean欄位名保持和資料庫欄位名是最好的選擇。
折騰resultMap extends屬性,表關聯查詢。
Employer.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="com.mybatis3.mappers.EmployerMapper">
<resultMap id="Employer" type="model.Employer">
</resultMap>
<resultMap type="model.Employer" id="EmployerWithEmployee"
extends="Employer">
<result property="em.id" column="id" />
<result property="em.first_name" column="first_name" />
<result property="em.last_name" column="last_name" />
<result property="em.salary" column="salary" />
</resultMap>
<select id="findEmployeeById2" resultMap="EmployerWithEmployee">
select employee_id,name,b.first_name,b.salary,b.last_name from Employer a
left join Employee b on a.employee_id=b.id where a.id = #{abc}
</select>
</mapper>
測試:
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);
SqlSession s = sf.openSession();
EmployerMapper employerMapper = s.getMapper(EmployerMapper.class);
Employer e2 = employerMapper.findEmployeeById2(1);
System.out.println(e2.getEmployee_id());
System.out.println(e2.getName());
System.out.println(e2.getEm().getFirst_name());
System.out.println(e2.getEm().getLast_name());
注意這次的em不再是和上面第一個折騰的一樣,是和方法名一致的。這次是和屬性名一致。不然會報錯。
而且MyBatis的關聯查詢就這麼簡單,還是一樣的關聯語句,只不過加了一些對映配置。
折騰association
extends拓展看起來挺好,但是講到解耦的話,你extends出來是個不倫不類的東西。本身我就有Employee的存在。
所以,這時association出現了。
<mapper namespace="com.mybatis3.mappers.EmployerMapper">
<resultMap id="Employee" type="model.Employee">
<id property="id" column="id" />
<result property="first_name" column="first_name" />
<result property="last_name" column="last_name" />
<result property="salary" column="salary" />
</resultMap>
<resultMap id="Employer" type="model.Employer">
<id property="id" column="id" /> <!-- id相當於resultmap的引用的唯一標識-->
<result property="name" column="name" /> <!-- property對應javabean的屬性名,column對應資料庫欄位名 -->
<result property="employee_id" column="employee_id" />
<association property="em" resultMap="Employee" />
</resultMap>
<select id="findEmployeeById2" resultMap="Employer">
select employee_id,name,b.first_name,b.salary,b.last_name from Employer a
left join Employee b on a.employee_id=b.id where a.id = #{abc}
</select>
</mapper>
測試程式碼不變:
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);
SqlSession s = sf.openSession();
EmployerMapper employerMapper = s.getMapper(EmployerMapper.class);
Employer e2 = employerMapper.findEmployeeById2(1);
System.out.println(e2.getEmployee_id());
System.out.println(e2.getName());
System.out.println(e2.getEme().getFirst_name());
System.out.println(e2.getEme().getLast_name());
s.close();
但是不同於resultmap使用extends,result標籤是不可少的,一旦少了,將獲取不到其屬性值。
經過上面種種折騰之後終於知道作者講的作用是什麼:最後就明白了書上所講的ResultMap的作用,對映SQL選擇宣告的結果到JavaBean屬性中。通過一對一和一對多associations可以將簡單選擇宣告映射覆雜的宣告。