細說 Spring 整合 Mybatis
GitHub:https://github.com/nateshao/ssm/tree/master/116-mybatis-spring
1. 整合環境搭建
“要實現MyBatis與Spring的整合,很明顯需要這兩個框架的JAR包,但是只使用這兩個框架中所提供的JAR包是不夠的,還需要其他的JAR包來配合使用,整合時所需準備的JAR包具體如下。
Spring框架所需的JAR包
- <dependencies>
- <!-- AOP開發使用的JAR -->
- <dependency>
- <groupId>aopalliance</groupId>
- <artifactId>aopalliance</artifactId>
- <version>1.0</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.9.6</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aop</artifactId>
- <version>5.3.8</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aspects</artifactId>
- <version>5.3.7</version>
- </dependency>
- <!-- 4個核心模塊JAR -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-beans</artifactId>
- <version>5.3.8</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>5.3.8</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>5.3.8</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-expression</artifactId>
- <version>5.3.8</version>
- </dependency>
- <!-- JDBC和事務的JAR -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-jdbc</artifactId>
- <version>5.3.8</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>5.3.8</version>
- </dependency>
- <dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- <version>1.2</version>
- </dependency>
- </dependencies>
MyBatis與Spring整合的中間JAR
- <!-- MyBatis與Spring整合的中間JAR -->
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis-spring</artifactId>
- <version>2.0.6</version>
- </dependency>
數據庫驅動JAR(MySQL)
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>5.1.47</version>
- </dependency>
數據源所需JAR(DBCP)
- <dependency>
- <groupId>commons-dbcp</groupId>
- <artifactId>commons-dbcp</artifactId>
- <version>1.4</version>
- </dependency>
- <dependency>
- <groupId>commons-pool</groupId>
- <artifactId>commons-pool</artifactId>
- <version>1.6</version>
- </dependency>
編寫配置文件
- 創建項目116-mybatis-spring,引入maven包
- 編寫db.properties
- 編寫Spring配置文件applicationContext.xml
- 編寫MyBatis配置文件mybatis-config.xml
- 引入log4j.properties
db.properties
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false
- jdbc.username=root
- jdbc.password=123456
- 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}" />
- <!--連接數據庫的url -->
- <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>
- <!--實例化Dao -->
- <bean id="customerDao" class="com.nateshao.dao.impl.CustomerDaoImpl">
- <!-- 注入SqlSessionFactory對象實例-->
- <property name="sqlSessionFactory" ref="sqlSessionFactory" />
- </bean>
- <!-- Mapper代理開發(基于MapperFactoryBean) -->
- <!-- <bean id="customerMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
- <property name="mapperInterface" value="com.nateshao.mapper.CustomerMapper" />
- <property name="sqlSessionFactory" ref="sqlSessionFactory" />
- </bean> -->
- <!-- Mapper代理開發(基于MapperScannerConfigurer) -->
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="com.nateshao.mapper" />
- </bean>
- <!-- 開啟掃描 -->
- <context:component-scan base-package="com.nateshao.service" />
- </beans>
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.nateshao.po" />
- </typeAliases>
- <!--配置Mapper的位置 -->
- <mappers>
- <mapper resource="mapper/CustomerMapper.xml" />
- <!-- Mapper接口開發方式 -->
- <mapper resource="mapper/CustomerMapperInterface.xml" />
- </mappers>
- </configuration>
log4j.properties
- # Global logging configuration
- log4j.rootLogger=ERROR, stdout
- # MyBatis logging configuration...
- log4j.logger.com.nateshao=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
這樣一來,環境加載文件就全了
2. 傳統DAO方式的開發整合
“采用傳統DAO開發方式進行MyBatis與Spring框架的整合時,可以使用mybatis-spring包中所提供的SqlSessionTemplate類或SqlSessionDaoSupport類來實現。
- SqlSessionTemplate:是mybatis-spring的核心類,它負責管理MyBatis的SqlSession,調用MyBatis的SQL方法。當調用SQL方法時,SqlSessionTemplate將會保證使用的SqlSession和當前Spring的事務是相關的。它還管理SqlSession的生命周期,包含必要的關閉、提交和回滾操作。
- SqlSessionDaoSupport:是一個抽象支持類,它繼承了DaoSupport類,主要是作為DAO的基類來使用。可以通過SqlSessionDaoSupport類的getSqlSession()方法來獲取所需的SqlSession。
代碼實現
CustomerDao.java
- public interface CustomerDao {
- // 通過id查詢客戶
- public Customer findCustomerById(Integer id);
- }
CustomerDaoImpl.java
- public class CustomerDaoImpl extends SqlSessionDaoSupport implements CustomerDao {
- // 通過id查詢客戶
- public Customer findCustomerById(Integer id) {
- return this.getSqlSession().selectOne("com.nateshao.po"
- + ".CustomerMapper.findCustomerById", id);
- }
- }
CustomerMapperInterface.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.nateshao.po.CustomerMapper">
- <!--根據id查詢客戶信息 -->
- <select id="findCustomerById" parameterType="Integer"
- resultType="customer">
- select * from t_customer where id = #{id}
- </select>
- </mapper>
測試類 DaoTest.java
- package com.nateshao.test;
- import com.nateshao.dao.CustomerDao;
- import com.nateshao.mapper.CustomerMapper;
- import com.nateshao.po.Customer;
- import org.junit.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @date Created by 邵桐杰 on 2021/10/26 15:12
- * @微信公眾號 程序員千羽
- * @個人網站 www.nateshao.cn
- * @博客 https://nateshao.gitee.io
- * @GitHub https://github.com/nateshao
- * @Gitee https://gitee.com/nateshao
- * Description:
- */
- public class DaoTest {
- @Test
- public void findCustomerByIdDaoTest() {
- ApplicationContext act =
- new ClassPathXmlApplicationContext("applicationContext.xml");
- // 根據容器中Bean的id來獲取指定的Bean
- CustomerDao customerDao =
- (CustomerDao) act.getBean("customerDao");
- // CustomerDao customerDao = act.getBean(CustomerDao.class);
- Customer customer = customerDao.findCustomerById(1);
- System.out.println(customer);
- }
- @Test
- public void findCustomerByIdMapperTest() {
- ApplicationContext act =
- new ClassPathXmlApplicationContext("applicationContext.xml");
- CustomerMapper customerMapper = act.getBean(CustomerMapper.class);
- Customer customer = customerMapper.findCustomerByIdOne(1);
- System.out.println(customer);
- }
- }
3. Mapper接口方式的開發整合
“在MyBatis+Spring的項目中,雖然使用傳統的DAO開發方式可以實現所需功能,但是采用這種方式在實現類中會出現大量的重復代碼,在方法中也需要指定映射文件中執行語句的id,并且不能保證編寫時id的正確性(運行時才能知道)。為此,我們可以使用MyBatis提供的另外一種編程方式,即使用Mapper接口編程。
基于MapperFactoryBean的整合
“MapperFactoryBean是MyBatis-Spring團隊提供的一個用于根據Mapper接口生成Mapper對象的類,該類在Spring配置文件中使用時可以配置以下參數:
- mapperInterface:用于指定接口;
- SqlSessionFactory:用于指定SqlSessionFactory;
- SqlSessionTemplate:用于指定SqlSessionTemplate。如果與SqlSessionFactory同時設定,則只會啟用SqlSessionTemplate。
注意!!!
“雖然使用Mapper接口編程的方式很簡單,但是在具體使用時還是需要遵循一些規范。
- Mapper接口的名稱和對應的Mapper.xml映射文件的名稱必須一致。
- Mapper.xml文件中的namespace與Mapper接口的類路徑相同。
- Mapper接口中的方法名和Mapper.xml中定義的每個執行語句的id相同。
- Mapper接口中方法的輸入參數類型要和Mapper.xml中定義的每個sql的parameterType的類型相同。
- Mapper接口方法的輸出參數類型要和Mapper.xml中定義的每個sql的resultType的類型相同。
“在實際的項目中,DAO層會包含很多接口,如果每一個接口都在Spring配置文件中配置,不但會增加工作量,還會使得Spring配置文件非常臃腫。為此,可以采用自動掃描的形式來配置MyBatis中的映射器——采用MapperScannerConfigurer類。
MapperScannerConfigurer類在Spring配置文件中可以配置以下屬性:
- basePackage:指定映射接口文件所在的包路徑,當需要掃描多個包時可以使用分號或逗號作為分隔符。指定包路徑后,會掃描該包及其子包中的所有文件。
- annotationClass:指定了要掃描的注解名稱,只有被注解標識的類才會被配置為映射器。
- sqlSessionFactoryBeanName:指定在Spring中定義的SqlSessionFactory的Bean名稱。
- sqlSessionTemplateBeanName:指定在Spring中定義的SqlSessionTemplate的Bean名稱。如果定義此屬性,則sqlSessionFactoryBeanName將不起作用。
- markerInterface:指定創建映射器的接口。
MapperScannerConfigurer的使用非常簡單,只需要在Spring的配置文件中編寫如下代碼:
- <!-- Mapper代理開發(基于MapperScannerConfigurer) -->
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="com.nateshao.mapper" />
- </bean>
通常情況下,MapperScannerConfigurer在使用時只需通過basePackage屬性指定需要掃描的包即可,Spring會自動的通過包中的接口來生成映射器。這使得開發人員可以在編寫很少代碼的情況下,完成對映射器的配置,從而提高開發效率。
4. 測試事務
如何進行事務測試?
在項目中,Service層既是處理業務的地方,又是管理數據庫事務的地方。要對事務進行測試,首先需要創建Service層,并在Service層編寫添加客戶操作的代碼;然后在添加操作的代碼后,有意的添加一段異常代碼(如int i = 1/0;)來模擬現實中的意外情況;最后編寫測試方法,調用業務層的添加方法。這樣,程序在執行到錯誤代碼時就會出現異常。
- @Service
- @Transactional
- public class CustomerServiceImpl implements CustomerService {
- //注解注入CustomerMapper
- @Autowired
- private CustomerMapper customerMapper;
- //添加客戶
- public void addCustomer(Customer customer) {
- this.customerMapper.addCustomer(customer);
- int i=1/0; //模擬添加操作后系統突然出現的異常問題
- }
- }
在沒有事務管理的情況下,即使出現了異常,數據也會被存儲到數據表中;如果添加了事務管理,并且事務管理的配置正確,那么在執行上述操作時,所添加的數據將不能夠插入到數據表中。
總結
這篇文章首先對MyBatis與Spring框架整合的環境搭建進行了講解,
然后講解了使用傳統DAO方式的開發整合,以及基于Mapper接口方式的開發整合。