輕鬆掌握Mybatis(上)

入門案例

現有一張數據表:

mysql> use mybatis;
Database changed
mysql> select * from tbl_employee;
+----+-----------+--------+-------------+
| id | last_name | gender | email       |
+----+-----------+--------+-------------+
|  1 | tom       | 0      | [email protected] |
+----+-----------+--------+-------------+
1 row in set (0.00 sec)

該如何通過MyBatis對其進行查詢?

首先創建對應的Java類:

package com.wwj.mybatis.bean;

public class Employee {
	
	private Integer id;
	private String lastName;
	private String email;
	private String gender;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	
	@Override
	public String toString() {
		return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]";
	}
}

其次編寫MyBatis的全局配置文件(mybatis-config.xml):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
 	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC"/>
      			<dataSource type="POOLED">
        			<property name="driver" value="com.mysql.jdbc.Driver"/>
        			<property name="url" value="jdbc:mysql:///mybatis"/>
      				<property name="username" value="root"/>
        			<property name="password" value="123456"/>
      			</dataSource>
    	</environment>
	</environments>
	<mappers>
		<mapper resource="EmployeeMapper.xml"/>
	</mappers>
</configuration>

全局配置文件中主要配置的是數據源信息,然後是最後的mappers標籤,該標籤配置的是sql語句的映射文件。

所以我們接着創建sql語句的映射文件(EmployeeMapper.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.wwj.mybatis.bean.Employee">
 	<select id="selectEmp" resultType="com.wwj.mybatis.bean.Employee">
    	select id,last_name lastName,email,gender from tbl_employee where id = #{id}
  	</select>
</mapper>

其中mapper標籤的namespace屬性設置的是需要映射的類全名;select標籤表示查詢語句,其中的id屬性是該sql的唯一標識,resultType表示返回值的類型;然後在select標籤中編寫需要執行的sql語句。

一切準備就緒後,開始編寫測試代碼:

@Test
void test() throws IOException {
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession session = sessionFactory.openSession();
	Employee employee = session.selectOne("com.wwj.mybatis.bean.Employee.selectEmp",1);
	System.out.println(employee);
	session.close();
}

通過全局的配置文件去創建一個SqlSessionFactory,並通過該對象獲得SqlSession,就可以使用SqlSession進行增刪改查了。這裏調用了selectOne方法,表示從數據表中查詢一行數據,其中的第一個參數需要填入剛纔在sql映射文件中設置的id,但爲了避免該id與其它sql語句重複,一般都會在id前加上namespace;第二個參數則是需要傳入sql的參數。

增刪改查的新方式

在入門案例中我們已經成功通過MyBatis查詢了數據表的數據,但是這種方式的缺點也是顯而易見的,爲此,MyBatis提供了一種更加完美的方式來操作數據表。

定義一個接口:

package com.wwj.mybatis.dao;

public interface EmployeeMapper {
	
	public Employee getEmpById(Integer id);
}

MyBatis神奇的地方就在於你不需要去實現該接口,只需要將該接口與對應的sql映射文件綁定即可,MyBatis會自動創建代理對象調用對應的方法。

所以我們需要對sql的映射文件做一個小小的改動:

<?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.wwj.mybatis.dao.EmployeeMapper">
 	<select id="getEmpById" resultType="com.wwj.mybatis.bean.Employee">
    	select id,last_name lastName,email,gender from tbl_employee where id = #{id}
  	</select>
</mapper>

首先是namespace,現在該屬性應該指向的是接口的全類名;然後是select標籤的id屬性,該屬性也應該指向接口中對應的方法名,其它地方不變。

測試代碼:

@Test
void test2() throws IOException{
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession session = sessionFactory.openSession();
	//Mybatis會爲接口自動創建代理對象,並由代理對象執行增刪改查
	EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
	Employee employee = mapper.getEmpById(1);
	System.out.println(employee);
	session.close();
}

這裏同樣是通過全局配置文件創建SqlSessionFactory,並通過該對象獲得SqlSession,不同的是,這裏需要通過SqlSession對象調用getMapper方法去獲得指定的接口的實現類,該實現類是MyBatis自動生成的代理對象,並通過該對象調用指定的方法完成數據表的操作。

通過properties標籤引入外部屬性文件

這個操作已經是再熟悉不過了,這裏直接貼出代碼:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	
	<!-- 使用properties標籤引入外部的屬性文件內容 -->
	<properties resource="dbconfig.properties"></properties>
	
 	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC"/>
      			<dataSource type="POOLED">
        			<property name="driver" value="${jdbc.driver}"/>
        			<property name="url" value="${jdbc.url}"/>
      				<property name="username" value="${jdbc.username}"/>
        			<property name="password" value="${jdbc.password}"/>
      			</dataSource>
    	</environment>
	</environments>
	<mappers>
		<mapper resource="EmployeeMapper.xml"/>
	</mappers>
</configuration>

typeAliases

這是一個全局配置文件的標籤,通過該標籤能夠爲某個Java類型設置別名,比如:

<typeAliases>
	<!-- type:指定要起別名的類型全類名,默認別名爲類名字母小寫:employee 
		 也可以使用alias屬性爲其設置指定的別名
	-->
	<typeAlias type="com.wwj.mybatis.bean.Employee" alias="employee"/>
</typeAliases>

這樣我們就可以修改sql映射文件中的返回值類型:

<select id="getEmpById" resultType="employee">
    select * from tbl_employee where id = #{id}
</select>

該標籤還能夠批量起別名,比如:

<typeAliases>
	<!-- 
		批量起別名
		name:指定包名(爲當前包及其子包下的所有類都起一個默認別名) 
	-->
	<package name="com.wwj.mybatis.bean"/>
</typeAliases>

若是子包下也有一個重名的類,則MyBatis會因爲別名重複而報錯,爲此,可以通過@Alias註解在類上設置新的別名。

environments

全局配置文件標籤,可以通過其子標籤environment配置多種環境,比如:

<environments default="development">
	<environment id="development">
		<transactionManager type="JDBC"/>
    		<dataSource type="POOLED">
      			<property name="driver" value="${jdbc.driver}"/>
       			<property name="url" value="${jdbc.url}"/>
     			<property name="username" value="${jdbc.username}"/>
        		<property name="password" value="${jdbc.password}"/>
      		</dataSource>
   	</environment>
    	
    <environment id="test">
    	<transactionManager type="JDBC"></transactionManager>
    	<dataSource type="POOLED"></dataSource>
    </environment>
</environments>

environment需要配置兩個子標籤:transactionManager和dataSource,否則就會報錯。

transactionManager標籤的type屬性可以指定兩個屬性值:

  1. JDBC:這個配置直接使用了 JDBC 的提交和回滾設施,它依賴從數據源獲得的連接來管理事務作用域
  2. MANAGED:這個配置幾乎沒做什麼。它從不提交或回滾一個連接,而是讓容器來管理事務的整個生命週期(比如 JEE 應用服務器的上下文), 默認情況下它會關閉連接

dataSource標籤的type屬性可以指定三個屬性值:

  1. UNPOOLED : 這個數據源的實現會每次請求時打開和關閉連接。雖然有點慢,但對那些數據庫連接可用性要求不高的簡單應用程序來說,是一個很好的選擇。 性能表現則依賴於使用的數據庫,對某些數據庫來說,使用連接池並不重要,這個配置就很適合這種情形。
  2. POOLED: 這種數據源的實現利用“池”的概念將 JDBC 連接對象組織起來,避免了創建新的連接實例時所必需的初始化和認證時間。 這種處理方式很流行,能使併發 Web 應用快速響應請求
  3. JNDI: 這個數據源實現是爲了能在如 EJB 或應用服務器這類容器中使用,容器可以集中或在外部配置數據源,然後放置一個 JNDI 上下文的數據源引用

mappers

sql映射文件標籤,用於將sql映射註冊到全局配置中,比如:

<mappers>
	<mapper resource="EmployeeMapper.xml"/>
</mappers>

使用子標籤mapper註冊一個sql映射。

mapper還有一個用法, 就是註冊接口,比如:

<mappers>
	<mapper class="com.wwj.mybatis.dao.EmployeeMapper"/>
</mappers>

需要注意的是,若要通過這樣的方式註冊接口,則需要將該sql映射文件名設置爲與接口名一致,並與接口放在同一目錄下。

mappers同樣支持批量註冊,使用package標籤即可,若使用批量註冊,sql映射文件也需要與接口同目錄,否則MyBatis將無法找到文件而報錯。

增刪改查

熟悉了MyBatis配置文件中的一些標籤後,我們來看看MyBatis是如何實現增刪改查操作的?

插入數據

仿照着實現查詢的方式,我們很容易寫出增刪改查,先修改接口:

package com.wwj.mybatis.dao;

public interface EmployeeMapper {
	
	public Employee getEmpById(Integer id);
	
	public void addEmp(Employee employee);
	
	public void updateEmp(Employee employee);
	
	public void deleteEmp(Integer id);
}

在接口中新添加了三個方法,分別對應着增刪改。

然後修改sql映射文件:

<?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.wwj.mybatis.dao.EmployeeMapper">
 	<select id="getEmpById" resultType="employee">
    	select * from tbl_employee where id = #{id}
  	</select>
  	
  	<insert id="addEmp" parameterType="com.wwj.mybatis.bean.Employee">
  		insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
  	</insert>
  	
  	<update id="updateEmp">
  		update tbl_employee set last_name = #{lastName},email = #{email},gender = #{gender} where id = #{id}
  	</update>
  	
  	<delete id="deleteEmp">
  		delete from tbl_employee where id = #{id}
  	</delete>
</mapper>

這已經很簡單了,無需做過多解釋,唯一要說的是parameterType屬性,該屬性的作用是指定方法參數的類型,該屬性可以省略不寫。這樣準備工作就完成了,來測試一下:

@Test
void test3() throws IOException{
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession session = sessionFactory.openSession();
	EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
	Employee employee = new Employee(null,"Jack","[email protected]","1");
	mapper.addEmp(employee);
	session.commit();
	session.close();
}

需要注意的是,SqlSession是不會自動提交數據的,所以在進行增刪改操作的時候,最後一定要記得提交。

刪除數據

做刪除操作只需要改變一下調用的方法即可:

@Test
void test3() throws IOException{
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession session = sessionFactory.openSession();
	EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
	mapper.deleteEmp(2);
	session.commit();
	session.close();
}

修改數據

修改數據同樣是這樣:

@Test
void test3() throws IOException{
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession session = sessionFactory.openSession();
	EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
	Employee employee = new Employee(1,"Jack","[email protected]","0");
	mapper.updateEmp(employee);
	session.commit();
	session.close();
}

Mybatis還直接允許增刪改操作直接定義以下返回值:Integer、Long、Boolean,直接在接口方法上定義即可,比如:

public interface EmployeeMapper {
	
	public Long addEmp(Employee employee);
}

查詢數據

查詢就不說了,入門案例已經寫過了。

獲取自增主鍵的值

MyBatis支持獲取自增主鍵的值,而且非常方便:

<insert id="addEmp" useGeneratedKeys="true" keyProperty="id">
  	insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
</insert>

只需要設置useGeneratedKeys屬性值爲true即可,MyBatis就會將主鍵的值封裝到keyProperty屬性指定的參數中,這裏指定了id,表示將自增主鍵的值獲取出來並存入Employee對象的id屬性中,接下來要想獲取主鍵的值就可以直接獲取該對象的id屬性了。

參數處理

下面介紹一下MyBatis對於參數的處理,在前面的案例中,我們都是通過#{參數名}的方式來獲取參數,而事實上,對於單個的參數,MyBatis不會對其進行特殊處理,這個參數名是可以隨便寫的,寫個a、b、c都可以,比如:

<select id="getEmpById" resultType="employee">
    select * from tbl_employee where id = #{aaa}
</select>

那麼對於多參數的方法該如何處理呢?

package com.wwj.mybatis.dao;

public interface EmployeeMapper {
	
	//新增一個多參數的方法
	public Employee getEmpByIdAndLastName(String id,String lastName);
	
	public Employee getEmpById(Integer id);
	
	public void addEmp(Employee employee);
	
	public void updateEmp(Employee employee);
	
	public void deleteEmp(Integer id);
}

在接口中新增一個getEmpByIdAndLastName方法,並添加對應的sql配置:

<select id="getEmpByIdAndLastName" resultType="employee">
 	select * from tbl_employee where id = #{id} and last_name = #{lastName}
</select>

可能大家會想當然地這樣寫,但告訴大家,這樣是錯誤的。

MyBatis會對多個參數進行特殊處理,將這些參數封裝成一個map,所以我們需要從map中取值,如下:

<select id="getEmpByIdAndLastName" resultType="employee">
 	select * from tbl_employee where id = #{param1} and last_name = #{param2}
</select>

MyBatis有着自己的封裝規則,它將傳遞過來的參數封裝到map中,指定鍵爲:param1、param2、param3...,而這些鍵對應的就是我們需要取出的值。

當然,你也可以這樣寫:

<select id="getEmpByIdAndLastName" resultType="employee">
 	select * from tbl_employee where id = #{0} and last_name = #{1}
</select>

通過索引獲取map中的值。

命名參數

這兩種獲取參數方式的缺點是顯而易見的,當參數足夠多時,這樣的參數名會使開發者眼花繚亂,爲此,我們應該使用命名參數的方式進行參數值的獲取。

這裏需要藉助@Param註解對map的鍵重命名:

//新增一個多參數的方法
public Employee getEmpByIdAndLastName(@Param("id")String id,@Param("lastName")String lastName);

這樣我們就能直接通過指定的參數名從map中獲取值了:

<select id="getEmpByIdAndLastName" resultType="employee">
 	select * from tbl_employee where id = #{id} and last_name = #{lastName}
</select>

處理POJO

若是傳入的參數過多,而且正好符合業務邏輯的模型對象,我們就可以直接傳入POJO,在取出數據值的時候就可以直接使用POJO的屬性名:#{POJO屬性名}

而如果多個參數並不符合模型對象,爲了方便,我們也可以自己將其封裝成一個map,比如:

//新增一個多參數的方法
public Employee getEmpByIdAndLastName(Map<String, Object> map);

那麼你在傳遞參數的時候就需要傳遞一個map:

@Test
void test4() throws IOException{
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession session = sessionFactory.openSession();
	//Mybatis會爲接口自動創建代理對象,並由代理對象執行增刪改查
	EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
	Map<String, Object> map = new HashMap<String, Object>();
	map.put("id", "1");
	map.put("lastName", "Jack");
	Employee employee = mapper.getEmpByIdAndLastName(map);
	System.out.println(employee);
	session.close();
}

而在取出map數據的時候就可以直接通過鍵獲取:

<select id="getEmpByIdAndLastName" resultType="employee">
 	select * from tbl_employee where id = #{id} and last_name = #{lastName}
</select>

特別需要注意的是,Mybatis會對Collection類型及數組做特殊處理,比如:

public Employee getEmpById(List<Integer> ids);

該參數是一個id的集合,若是想從該集合中獲取第一個id的值,則需要#{list[0]}

因爲對於Collection類型,包括:Collection、List、Set,MyBatis都會將其封裝到map中,其對應的鍵爲collection,如果是List類型,還可以使用list作爲鍵,數組的鍵爲array

#{}與${}的區別

MyBatis中除了可以使用#{}取值外,還可以使用${},它們的用法是相同的,那麼這兩種方式到底有什麼區別呢?

我分別用#{}和${}進行取值,並執行測試代碼,下面是運行結果:

DEBUG 04-16 13:46:27,992 ==>  Preparing: select * from tbl_employee where id = ? and last_name = ?   (BaseJdbcLogger.java:145) 
DEBUG 04-16 14:31:13,054 ==>  Preparing: select * from tbl_employee where id = 1 and last_name = Jack   (BaseJdbcLogger.java:145) 

會發現,兩者的區別在於,${}會將傳遞的參數顯示到生成的sql語句上。

select元素

select標籤用來定義查詢操作,其中有三個比較重要的參數:

  1. id:唯一標識符,用來引用這條語句,需要與接口的方法名一致
  2. parameterType:參數類型,可以不傳,MyBatis會根據TypeHandler自動判斷
  3. resultType:返回值類型,別名或者全類名,如果返回的是集合,則寫的是集合中元素的類型;不能與resultMap同時使用

在前面的案例中,我們已經使用過select標籤,接下來讓我們深入瞭解一下該標籤。

比如在接口中定義這樣的一個方法:

public List<Employee> getEmpsByLastNameLike(String lastName);

該方法的返回值是集合類型,那麼在編寫sql配置的時候就得這樣寫:

<select id="getEmpsByLastNameLike" resultType="employee">
 	select * from tbl_employee where last_name like #{lastName}
</select>

resultType寫的是集合中的元素類型。

若凡返回值是map類型,比如:

public Map<String,Object> getEmpMapById(Integer id);

sql配置應該這樣寫:

<select id="getEmpMapById" resultType="map">
 	select * from tbl_employee where id = #{id}
</select>

resultType寫的是map,爲什麼能夠直接寫map而不用寫全類名,因爲MyBatis已經幫我們取好了別名。

通過這樣的方式,MyBatis會將表中的列名和記錄作爲鍵和值一一封裝到map中。

我們還可以通過返回map來查詢表中的某一行數據,並直接將其封裝成對象返回:

@MapKey("id")
public Map<Integer,Employee> getEmpByLastNameLike(String lastName);

該方法能將查詢到的每一行數據封裝成一個對象,其鍵由@MapKey註解指定,比如這裏是指定以id爲鍵,接下來是sql配置:

<select id="getEmpByLastNameLike" resultType="employee">
 	select * from tbl_employee where last_name like #{lastName}
</select>

resultType同樣是集合元素類型,但是通過該sql查詢返回的結果將是以id爲鍵,對應的行數據爲值的map集合。

當然,select標籤可不止id、parameterType和resultType這三個參數,下面介紹一下該標籤的一些其它參數。

resultMap

我們知道,通過resultType指定返回值類型後,MyBatis會自動將得到的數據封裝進去,然而當數據表的列名和返回值屬性不一致時,就會導致封裝失敗,這時候我們會有兩種辦法:一種就是設置別名;另一種就是使用resultMap來自定義返回值類型。

比如:

public Employee getEmpById(Integer id);

按照之前的寫法,應該是這樣:

<select id="getEmpById" resultType="employee">
    select * from tbl_employee where id = #{id}
 </select>

但現在,倘若Employee類中的某些屬性名和表中的列名並不一致,此時MyBatis將無法進行自動封裝,我們就需要通過resultMap來自定義封裝規則。

<!-- 自定義某個JavaBean的封裝規則 -->
<resultMap type="employee" id="emp">
	<!-- 
 		指定主鍵列的封裝規則
 		column:指定哪一列
 		property:指定對應的JavaBean屬性 
 	-->
 	<id column="id" property="id"/>
 	<!-- 指定非主鍵列的封裝規則 -->
 		<result column="last_name" property="lastName"/>
 		<result column="email" property="email"/>
 		<result column="gender" property="gender"/>
 	</resultMap>
 
<select id="getEmpById" resultMap="emp">
	select * from tbl_employee where id = #{id}
</select>

事實上,對於主鍵列,你也可以使用result標籤來指定規則, 但是使用id標籤的好處就是MyBatis會知道該屬性是主鍵從而自動設置一些功能,對於一些屬性名和列名已經一致的屬性,你也可以不進行自定義,MyBatis還是會自動進行封裝的。

resultMap可以用來解決數據表的聯合查詢問題,現有兩張數據表,一張員工表:

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| last_name | varchar(255) | YES  |     | NULL    |                |
| gender    | char(1)      | YES  |     | NULL    |                |
| email     | varchar(255) | YES  |     | NULL    |                |
| d_id      | int(11)      | YES  | MUL | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+

一張部門表:

+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| dept_name | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+

其中員工表的d_id列與部門表的id列存在外鍵約束關係。

若有這樣的需求,查詢員工表的某位員工信息,同時查出它的部門信息,該需求涉及到聯合查詢的問題,resultMap則能夠很好地解決這一問題。

首先我們創建兩張數據表對應的類,員工類:

package com.wwj.mybatis.bean;

public class Employee {
	
	private Integer id;
	private String lastName;
	private String email;
	private String gender;
	private Department department;
    
    public Employee() {
		
	}

	public Department getDepartment() {
		return department;
	}

	public void setDepartment(Department department) {
		this.department = department;
	}
    
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
}

部門類:

package com.wwj.mybatis.bean;

public class Department {
	
	private Integer id;
	private String departmentName;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getDepartmentName() {
		return departmentName;
	}
	public void setDepartmentName(String departmentName) {
		this.departmentName = departmentName;
	}
}

那麼接下來就非常簡單了,在接口中定義查詢方法:

public Employee getEmpAndDept(Integer id);

編寫sql配置:

<resultMap type="employee" id="empy">
 	<id column="id" property="id"/>
 	<result column="last_name" property="lastName"/>
 	<result column="gender" property="gender"/>
 	<result column="did" property="dept.id"/>
 	<result column="dept_name" property="dept.departmentName"/>
</resultMap>
<select id="getEmpAndDept" resultMap="empy">
	select * from tbl_employee e,tbl_dept d where e.d_id=d.id and e.id=#{id}
</select>

這裏通過級聯屬性爲部門類的屬性定義規則。

除了級聯屬性,你也可以使用association標籤來定義規則:

<resultMap type="employee" id="empy">
 	<id column="id" property="id"/>
 	<result column="last_name" property="lastName"/>
 	<result column="gender" property="gender"/>
 	<!-- 
 		association可以指定聯合的Java對象
		property:指定哪個屬性爲聯合的Java對象
		javaType:指定聯合Java對象的類型
	-->
 	<association property="dept" javaType="com.wwj.mybatis.bean.Department">
 		<id column="did" property="id"/>
 		<result column="dept_name" property="departmentName"/>
 	</association>
</resultMap>
<select id="getEmpAndDept" resultMap="empy">
 	select * from tbl_employee e,tbl_dept d where e.d_id=d.id and e.id=#{id}
</select>

而有些情況,我們在查詢員工信息的時候並不需要查詢它的部門信息,此時可以使用延遲加載,實現非常簡單,在MyBatis的配置文件中進行兩個配置即可:

<settings>
	<setting name="lazyLoadingEnabled" value="true"></setting>
	<setting name="aggressiveLazyLoading" value="false"/>
</settings>

此時當我們不去查詢員工的部門信息時,Mybatis就不會發送sql去查詢部門表,避免了資源的浪費。

而當查詢對象中包含集合數據時,比如:

package com.wwj.mybatis.bean;

public class Department {
	
	private Integer id;
	private String departmentName;
	private List<Employee> emps;
	
	public List<Employee> getEmps() {
		return emps;
	}
	public void setEmps(List<Employee> emps) {
		this.emps = emps;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getDepartmentName() {
		return departmentName;
	}
	public void setDepartmentName(String departmentName) {
		this.departmentName = departmentName;
	}
	@Override
	public String toString() {
		return "Department [id=" + id + ", departmentName=" + departmentName + ", emps=" + emps + "]";
	}
}

一個部門包含若干員工,這些員工將封裝到一個集合中,該如何對其進行處理呢?

在接口中定義方法:

public Department getDeptById(Integer id);

sql配置:

<resultMap type="com.wwj.mybatis.bean.Department" id="MyDept">
 	<id column="did" property="id"/>
 	<result column="dept_name" property="departmentName"/>
 	<collection property="emps" ofType="com.wwj.mybatis.bean.Employee">
 		<!-- 定義集合中的元素封裝規則 -->
 		<id column="eid" property="id"/>
 		<result column="last_name" property="lastName"/>
 		<result column="email" property="email"/>
 		<result column="gender" property="gender"/>
 	</collection>
 </resultMap>
 <!-- 查詢部門的時候將部門對應的所有員工信息查詢出來 -->
 <select id="getDeptById" resultMap="MyDept">
 	SELECT * FROM tbl_dept d LEFT JOIN tbl_employee e ON d.id=e.d_id WHERE d.id=#{id} 
 </select>

其中collection用於定義集合中的元素封裝規則,ofType屬性指定集合的元素類型。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章