入門案例
現有一張數據表:
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屬性可以指定兩個屬性值:
- JDBC:這個配置直接使用了 JDBC 的提交和回滾設施,它依賴從數據源獲得的連接來管理事務作用域
- MANAGED:這個配置幾乎沒做什麼。它從不提交或回滾一個連接,而是讓容器來管理事務的整個生命週期(比如 JEE 應用服務器的上下文), 默認情況下它會關閉連接
dataSource標籤的type屬性可以指定三個屬性值:
- UNPOOLED : 這個數據源的實現會每次請求時打開和關閉連接。雖然有點慢,但對那些數據庫連接可用性要求不高的簡單應用程序來說,是一個很好的選擇。 性能表現則依賴於使用的數據庫,對某些數據庫來說,使用連接池並不重要,這個配置就很適合這種情形。
- POOLED: 這種數據源的實現利用“池”的概念將 JDBC 連接對象組織起來,避免了創建新的連接實例時所必需的初始化和認證時間。 這種處理方式很流行,能使併發 Web 應用快速響應請求
- 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標籤用來定義查詢操作,其中有三個比較重要的參數:
- id:唯一標識符,用來引用這條語句,需要與接口的方法名一致
- parameterType:參數類型,可以不傳,MyBatis會根據TypeHandler自動判斷
- 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屬性指定集合的元素類型。