目錄
10.1 整合環境搭建
MyBatis和Spring的整合開發環境主要涉及的jar包和編寫的配置文件
10.1.1 準備的jar包
- Spring框架所需的jar包
Spring框架所需要準備的JAR包共10個,其中包括4個核心模塊JAR、AOP開發使用的JAR、JDBC和事務的JAR(其中核心容器依賴的commons-logging的JAR在MyBatis框架的lib包中已經包含)
- aopalliance-1.0.jar
- aspectjweaver-1.8.10.jar
- spring-aop-4.3.6.RELEASE.jar
- spring-aspects-4.3.6.RELEASE.jar
- spring-beans-4.3.6.RELEASE.jar
- spring-context-4,3.6.RELEASE.jar
- spring-core-4.3.6.RELEASE.jar
- spring-expression-4.3.6.RELEASE.jar
- spring-jdbc-4.3.6.RELEASE.jar
- spring-tx-4.3.6.RELEASE.jar
- MyBatis框架的JAR包
MyBatis框架需要準備的JAR包共13個,其中包括核心包mybatis-3.4.2.jar及其解壓文件夾中lib目錄中的所有JAR
- ant-1.9.6.jar
- ant-launcher-1.9.6.jar
- asm-5.1.jar
- cglib-3.2.4.jar
- commons-logging-1.2.jar
- javassist-3.21.0-GA.jar
- log4j-1.2.17.jar
- log4j-api-2.3ar
- log4j-core-2.3.jar
- mybatis-3.4.2.jar
- ognl-3.1.12.jar
- slf4j-api-1.7.22.jar
- slf4j-log4j12-1.7.22.jar
- MyBatis與Spring整合所需的中間JAR包
爲了滿足MyBatis用戶對Spring框架的需求,MyBatis社區開發了一個用於整合MyBatis和Spring兩個框架的中間件——MyBatis-Spring。
這裏使用的中間件是mybatis-spring-1.3.1jar。此版本的JAR包可以通過鏈接獲取戳這裏 - 數據庫驅動JAR包
- mysql-connector-java-5.1.7-bin.jar。
- 數據源所需JAR包
整合時所使用的是DBCP數據源,所以需要準備DBCP和連接池的JAR包
- commons-dbcp2-2.1.1.jar
- commons-pool2-2.4.2.jar
10.1.2 編寫配置文件
步驟一
創建項目(名字自取),並將上述所有的jar包添加到項目的lib包中併發布到類路徑去。
步驟二
在項目的src目錄下分別創建db_properties,Spring的配置文件applicationContext.xml,以及MyBatis的核心配置文件mybatis-config.xml。
db_properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_mybatis
jdbc.username=root
jdbc.password=root
jdbc.maxTotal=30
jdbc.maxIdle=10
jdbc.initialSize=5
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!--讀取db.properties-->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置數據源 -->
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource">
<!--數據庫驅動 -->
<property name="driverClassName" value="${jdbc.driver}" />
<!--連接數據庫的ur1 -->
<property name="url" value="${jdbc.url}" />
<!--連接數據庫的用戶名 -->
<property name="username" value="${jdbc.username}" />
<!--連接數據庫的密碼-->
<property name="password" value="${jdbc.password}" />
<!--最大連接數-->
<property name="maxTotal" value="${jdbc.maxTotal}" />
<!--最大空閒連接-->
<property name="maxIdle" value="${jdbc.maxIdle}" />
<!--初始化連接數-->
<property name="initialSize" value="${jdbc.initialSize}" />
</bean>
<!--事務管理器,依賴於數據源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--註冊事務管理器驅動,開啓事務註解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--配置MyBatis工廠 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入數據源 -->
<property name="dataSource" ref="dataSource" />
<!--指定核心配置文件位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>
<bean id="userDao" class="com.ssm.dao.impl.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
</beans>
首先定義了讀取properties文件的配置,然後配置了數據源,接下來配置了事務管理器並開啓了事務註解,最後配置了MyBatis工廠來與Spring整合。其中,MyBatis工廠的作用是構建SqlSessionFactory,它是通過MyBatis-Spring包中提供的org.mybatis.Spring.SqlSessionFactoryBean類來配置的。通常在配置時需要提供兩個參數:一個是數據源;另一個是MyBatis的配置文件路徑。這樣Spring的IoC容器就會在初始化id爲sqlSessionFactory的Bean時解析MyBatis的配置文件,並與數據源一同保存到Spring的Bean中。
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>
<!--配置別名 -->
<typeAliases>
<package name="com.ssm.po"/>
</typeAliases>
<!--配置Mapper的位置 -->
<mappers>
.....
</mappers>
</configuration>
由於在Spring中已經配置了數據源信息,因此在MyBatis的配置文件中不再需要配置數源信息。這裏只需要使用< typeAliases>和< mappers>元素來配置文件別名以及指定mapper文件位置即可。
此外,還需在項目的src目錄下創建log4j.properties文件,
代碼如下
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.ssm=DEBUG
Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
10.2 整合
上述已經完成對MyBatis和Spring整合開發環境的搭建工作,這些配置基本完成了這兩大框架大部分的整合工作。
下面是對傳統DAO方式和Mapper接口方式的開發整合的介紹
10.2.1 傳統DAO方式的開發整合
採用傳統DAO開發方式進行MyBatis與Spring框架的整合時,我們需要編寫DAO接口以及接口的實現類,並且需要向DAO實現類中注入SqlSessionFactory,然後在方法體內通過SqlSessionFactory創建SqlSession。爲此,我們可以使用Mybatis-Spring包中所提供的SqlSessionTemplate類或SqlSessionDaoSupport類來實現此功能。這兩個類的描述如下。
- SqlSessionTemplate:Mybatis-Spring的核心類,它負責管理MyBatis的SqlSession,調用MyBatis的SQL方法。當調用SQL方法時,SqlSessionTemplate將會保證使用的SqlSession和當前Spring的事務是相關的。它還管理SqlSession的生命週期,包含必要的關閉、提交和回滾操作。
- SqlSessionDaoSupport:一個抽象支持類,它繼承了DaoSupport類,主要是作爲DAO的基類來使用。可以通SqlSessionDaoSupport類的getSqlSession()方法來獲取所需的SqlSession。
1.實現持久層
在包中創建持久化類用戶類User,並定義相關方法,屬性,
package com.ssm.po;
public class User {
private Integer id;
private String username;
private String jobs;
private String phone;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getJobs() {
return jobs;
}
public void setJobs(String jobs) {
this.jobs = jobs;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String toString() {
return "User [id=" + id + ", username=" + username + ", jobs=" + jobs + ", phone=" + phone + "]";
}
}
1.1
創建映射文件UserMapper.xml,編寫根據id查詢用戶信息的映射語句
<?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.ssm.po.UserMapper">
<!--根據用戶編號獲取用戶信息 -->
<select id="findUserById" parameterType="Integer" resultType="User">
select * from t_user where id=#{id}
</select>
</mapper>
1.2
在MyBatis核心配置文件中配置映射文件UserMapper.xml的位置
<mappers>
<mapper resource="com/ssm/po/UserMapper.xml" />
<!--<mapper resource="com/ssm/mapper/UserMapper.xml" />-->
</mappers>
2.實現Dao層
2.1
創建接口UserDao,並在接口中編寫通過id查詢用戶的方法
package com.ssm.dao;
import com.ssm.po.User;
public interface UserDao {
public User findUserById(Integer id);
}
2.2
創建UserDAO接口的實現類,UserDaoImpl.java
package com.ssm.dao.impl;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import com.ssm.dao.UserDao;
import com.ssm.po.User;
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User findUserById(Integer id) {
return this.getSqlSession().selectOne("com.ssm.po.UserMapper.findUserById", id);
}
}
- UserDaoImpl類繼承了SqlSessionDaoSupport並實現了UserDao接口。其中,SqlSessionDaoSupport類在使用時需要一個SqlSessionFactory或一個SqlSessionTemplate對象,所以需要通過Spring給SqlSessionDaoSupport類的子類對象注入一個SqlSessionFactory或SqlSessionTemplate。這樣,子類中就能通過調用SqlSessionDaoSupport類的getSqlSession()方法來獲取SqlSession對象,並使用SqlSession對象中的方法了。
2.3
在Spring的配置文件中編寫UserDaoImpl的配置
<bean id="userDao" class="com.ssm.dao.impl.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
上述代碼創建了一個id爲userDao的Bean,並將SqlSessionFactory對象注入該Bean的實例化對象中。
3.整合測試
創建測試類,並編寫測試方法
package com.ssm.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ssm.dao.UserDao;
import com.ssm.po.User;
public class UserDaoTest {
@Test
public void findUserByIdDaotest(){
//1.初始化Spring容器,加載配置文件
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//2.通過容器獲取userDao實例
UserDao userDao=(UserDao)applicationContext.getBean("userDao");
//UserDao userDao=applicationContext.getBean(UserDao.class);
User user=userDao.findUserById(1);
System.out.println(user);
}
}
在上述方法中,我們採用的是根據容器中Bean的id來獲取指定Bean的方式。執行上述方法後,控制檯的輸出結果
從中可以看出,通過UserDao實例的findUserById()方法已經查詢出了id爲1的用戶信息,這就說明MyBatis與Spring整合成功。
10.2.2 Mapper接口方式的開發整合
MyBatis+Spring的項目中,雖然使用傳統的DAO開發方式可以實現所需功能,但是採用這種方式在實現類中會出現大量的重複代碼,在方法中也需要指定映射文件中執行語句的id,並且不能保證編寫時id的正確性(運行時才能知道)。爲此,我們可以使用MyBatis提供的另一種編程方式,即使用Mapper接口編程。接下來將講解如何使用 Mapper接口方式來實現MyBatis與Spring的整合。
1. 基於MapperFactoryBean的整合
MapperFactoryBean是MyBatis-Spring團隊提供的一個用於根據Mapper接口生成Mapper對象的類,該類在Spring配置文件中使用時可以配置以下參數。
- mapperInterface:用於指定接口。
- SqlSessionFactory:用於指定SqlSessionFactory。
- SqlSessionTemplate:用於指定SqlSessionTemplate。若與SqlSessionFactory同時設定,則只會啓用SqlsessionTemplate。
步驟一
在src目錄下創建一裝映射文件的包,並創建UserMapper接口以及對應的映射文件
UserMapper.java
package com.ssm.mapper;
import com.ssm.po.User;
public interface UserMapper {
public User findUserById(Integer id);
}
UserMapper.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.ssm.mapper.UserMapper">
<!--根據用戶編號獲取用戶信息 -->
<select id="findUserById" parameterType="Integer" resultType="User">
select * from t_user where id=#{id}
</select>
</mapper>
步驟二
在MyBatis中引入新的映射文件
<!--配置Mapper的位置 -->
<mappers>
<mapper resource="com/ssm/po/UserMapper.xml" />
<!--<mapper resource="com/ssm/mapper/UserMapper.xml" />-->
</mappers>
步驟三
在Spring的配置文件中創建一個id爲userMapper的Bean,
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.ssm.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
上述配置代碼爲MapperFactoryBean指定了接口以及SqlSessionFactory。
步驟四
在測試類UserDaoTest中編寫測試方法findUserByIdMapperTest()
@Test
public void findUserByldMapperTest(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper=(UserMapper)applicationContext.getBean("userMapper");
User user=userMapper.findUserById(1);
System.out.println(user);
}
注意
Mapper接口編程方式是,只需要程序員編寫Mapper接口(相當於DAO接口),然後由MyBatis框架根據接口的定義創建接口的動態代理對象,這個代理對象的方法體等同於DAO接口的實現類方法。
雖然使用Mapper接口編程的方式很簡單,但是在具體使用時還是需要遵循以下規範。
- Mapper接口的名稱和對應的Mapper.xml映射文件的名稱必須一致。
- Mapper.xml文件中的namespace與Mapper接口的類路徑相同(即接口文件和映射文件需要放在同一個包中)。
- Mapper接口中的方法名和Mapper.xml中定義的每個執行語句的id相同。
- Mapper接口中方法的輸入參數類型要和Mapper.xml中定義的每個SQL的parameterType的類型相同。
- Mapper接口方法的輸出參數類型要和Mapper.xml中定義的每個SQL的resultType的類型相同。
只要遵循了這些開發規範,MyBatis就可以自動生成Mapper接口實現類的代理對象,從而簡化開發。
2. 基於MapperScannerConfigurer的整合
在實際的項目中,DAO層會包含很多接口,如果每一個接口都那樣在Spring配置文件中配置,那麼不但會增加工作量,還會使得Spring配置文件非常臃腫。爲此,MyBatis-Spring團隊提供了一種自動掃描的形式來配置MyBatis中的映射器——採用MapperScannerConfigurer類。
MapperScannerConfigurer類在Spring配置文件中使用時可以配置以下屬性。
- basePackage:指定映射接口文件所在的包路徑,當需要掃描多個包時可以使用分號或逗號作爲分隔符。指定包路徑後,會掃描該包及其子包中的所有文件。
- annotationClass:指定要掃描的註解名稱,只有被註解標識的類纔會被配置爲映射器。
- sqlSessionFactoryBeanName:指定在Spring中定義的SqlSessionFactory的Bean名稱。
- sqlSessionTemplateBeanName:指定在Spring中定義的SqlSessionTemplate的Bean名稱。若定義此屬性,則sqlSessionFactoryBeanName將不起作用。
- markerInterface:指定創建映射器的接口。
MapperScannerConfigurer的使用非常簡單,只需要在Spring的配置文件中編寫如下代碼:
在通常情況下,MapperScannerConfigurer在使用時只需通過basePackage屬性指定需要掃描的包即可。
Spring會自動地通過包中的接口生成映射器。這使得開發人員可以在編寫很少代碼的情況下完成對映射器的配置,從而提高開發效率。
要驗證上面的配置很容易,只需將上述配置代碼寫入Spring的配置文件,並將基於MapperFactoryBean的整合案例中的步驟02和步驟03的代碼註釋掉,再次執行findUserByIdMapperTest()方法進行測試即可。方法執行後結果一致。