MyBatis与Spring整合
1、整合环境搭建
这里创建的是maven工程,因此在pom.xml文件中需要引入如下jar包。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.epoint</groupId>
<artifactId>MyBatis_Spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<org.springframework.version>4.3.7.RELEASE</org.springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>5.1</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.21.0-GA</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.1.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.22</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.22</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- spring start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument-tomcat</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc-portlet</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- spring end -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
其中包含了Spring框架所需的jar包、MyBatis框架所需要的jar包、Mybatis与Spring整合的中间jar包mybatis-spring、数据库驱动包以及数据源所需jar包(整合时所使用的DBCP数据源)。
2、编写配置文件
2.1、创建db.properties文件
该文件中除了配置了连接数据库基本4项还包括了数据库连接池的最大连接数(maxTotal)、最大空闲连接数(maxIdle)以及初始化连接数(initialSize)。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=Gepoint
jdbc.maxTotal=30
jdbc.maxIdle=10
jdbc.initialSize=5
2.2、创建applicationContent.xml文件
该文件中定义了读取properties文件配置,然后配置数据源,接下来配置事务管理器并开启事务注解,最后配置MyBaits工厂和Spring整合。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.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>
</beans>
其中,MyBatis工厂的作用就是构建SqlSessionFactory,通过mybatis-spring包中提供的org.mybatis.spring.SqlSessionFactoryBean类进行配置。通常该配置中需要提供两个参数:一个是数据源,另一个是MyBatis的配置文件路径。
2.3、创建mybatis-config.xml文件
由于数据源已在Spring中进行配置,因此在MyBatis的配置文件中不需要再配置数据源信息。只需要使用<typeAliases>
和<mappers>
元素来配置文件别名以及指定Mapper文件位置即可。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "http://mybatis.org/dtd/mybatis-3-config.dtd" "mybatis-3-config.dtd" >
<configuration>
<!-- 配置别名 -->
<typeAliases>
<package name="com.epoint.po"/>
</typeAliases>
<!-- 配置Mapper的位置 -->
<mappers>
...
</mappers>
</configuration>
2.4、 创建log4j.properties文件
配置日志记录文件。
# Global logging confguration
log4j.rootLogger=ERROR, stdout
# MyBatis logging confguration ...
log4j.logger.com.epoint=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
3、传统DAO方式的开发整合
采用传统DAO开发方式进行MyBatis与Spring框架的整合时,需要编写DAO接口以及接口实现类,并需要将DAO实现类注入SqlSessionFactory。
3.1、创建表customer
CREATE TABLE `t_customer` (
`id` INT (32) NOT NULL AUTO_INCREMENT,
`username` VARCHAR (50) DEFAULT NULL,
`jobs` VARCHAR (50) DEFAULT NULL,
`phone` VARCHAR (16) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = INNODB AUTO_INCREMENT = 9 DEFAULT CHARSET = utf8mb4
3.2、创建持久化类
创建一个com.epoint.po包,并在包中创建持久化类Customer,并添加setter和getter方法以及重写toString方法。
package com.epoint.po;
public class Customer {
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 "Customer [id=" + id + ", username=" + username + ", jobs=" + jobs + ", phone=" + phone + "]";
}
}
3.3、创建映射文件
在包com.epoint.mapper中创建映射文件CustomerMapper.xml,在该文件中编写根据id查询客户信息的映射语句。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd" "mybatis-3-mapper.dtd" >
<mapper namespace="com.epoint.mapper.CustomerMapper">
<!-- 根据id查询客户信息 --->
<select id="findCustomerById" parameterType="Integer"
resultType="customer">
select * from t_customer where id = #{id}
</select>
</mapper>
3.4、在MyBatis核心配置文件添加映射文件
<mapper resource="com/epoint/mapper/CustomerMapper.xml"/>
3.5、创建接口
创建一个com.epoint.dao包,并在包中创建接口CustomerDao,在接口中编写一个通过id查询客户信息的方法findCustomerById()。
package com.epoint.dao;
import com.epoint.po.Customer;
public interface CustomerDao {
// 通过id查询客户
public Customer findCustomerById(Integer id);
}
3.6、创建接口实现类
创建一个com.epoint.dao.impl包,并在包中创建CustomerDao接口的实现类CustomerDaoImpl,该类还需要继承SqlSessionDaoSupport类。
package com.epoint.dao.impl;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import com.epoint.dao.CustomerDao;
import com.epoint.po.Customer;
public class CustomerDaoImpl extends SqlSessionDaoSupport implements CustomerDao {
// 通过id查询客户
public Customer findCustomerById(Integer id) {
return this.getSqlSession().selectOne("com.epoint.mapper.CustomerMapper.findCustomerById" ,id);
}
}
3.7、applicationContext.xml添加配置
<!-- 实例化Dao -->
<bean id="customerDao" class="com.epoint.dao.impl.CustomerDaoImpl">
<!-- 注入SqlSessionFactory对象实例 -->
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
3.8、整合测试
创建一个com.epoint.test包,在包中创建测试类DaoTest,并编写测试方法findCustomerByIdDaoTest()。
package com.epoint.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.epoint.dao.CustomerDao;
import com.epoint.po.Customer;
public class DaoTest {
@Test
public void findCustomerByIdDaoTest() {
ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
// 根据容器中bean的id来获取指定的bean
CustomerDao customerDao = (CustomerDao) act.getBean("customerDao");
Customer customer = customerDao.findCustomerById(1);
System.out.println(customer);
}
}
运行,测试结果如下
DEBUG [main] - ==> Preparing: select * from t_customer where id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
Customer [id=1, username=Joy, jobs=docter, phone=111111111]
4、Mapper接口方式的开发整合
虽然传统的DAO开发方式可以实现所需功能,但是采用这种方式在实现类中会出现大量的重复代码,在开发是也需要指定映射文件中执行语句的id,并不能保证编写时id的正确性(运行时才能知道)。因此MyBatis提供了另外一种编程方式,即使用Mapper接口编程。
4.1、创建接口
在包com.epoint.mapper中创建CustomerMapper接口
package com.epoint.mapper;
import com.epoint.po.Customer;
public interface CustomerMapper {
// 通过id查询客户
public Customer findCustomerById(Integer id);
}
4.2、配置映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd" "mybatis-3-mapper.dtd" >
<mapper namespace="com.epoint.mapper.CustomerMapper">
<!-- 根据id查询客户信息 --->
<select id="findCustomerById" parameterType="Integer"
resultType="customer">
select * from t_customer where id = #{id}
</select>
</mapper>
4.3、在MyBatis核心配置文件添加映射文件
<mapper resource="com/epoint/mapper/CustomerMapper.xml"/>
4.4、applicationContext.xml添加配置
<!-- Mapper代理开发 -->
<bean id="customerMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.epoint.mapper.CustomerMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
4.5、整合测试
在DaoTest测试类中,添加测试方法findCustomerByIdMapperTest()。
@Test
public void findCustomerByIdMapperTest() {
ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
CustomerMapper customerMapper = act.getBean(CustomerMapper.class);
Customer customer = customerMapper.findCustomerById(1);
System.out.println(customer);
}
运行,测试结果如下
DEBUG [main] - ==> Preparing: select * from t_customer where id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
Customer [id=1, username=Joy, jobs=docter, phone=111111111]
5、事务测试
在MyBatis与Spring整合中,事务是由Spring进行管理的。在进行配置applicationContext.xml文件时已经配置了事务管理器,并开启了事务注解。 在实际项目开发中,业务层(service)既是处理业务的地方,又是管理数据库事务的地方。
5.1、编写添加操作的测试方法
在CustomerMapper接口中,编写测试方法addCustomer()。
// 添加客户
public void addCustomer(Customer customer);
5.2、在映射文件中编写执行插入操作的SQL
<!-- 添加客户信息 -->
<insert id="addCustomer" parameterType="customer">
insert into t_customer(username,jobs,phone)
values(#{username},#{jobs},#{phone})
</insert>
5.3、编写业务接口
创建一个com.epoint.service包,并在包中创建接口CustomerService,在接口中编写添加客户的方法addCustomer()
package com.epoint.service;
import com.epoint.po.Customer;
public interface CustomerService {
public void addCustomer(Customer customer);
}
5.4、编写接口实现类
创建一个com.epoint.service.impl包,并在包中创建CustomerServiceImpl接口实现类,来实现接口中的方法。
package com.epoint.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.epoint.mapper.CustomerMapper;
import com.epoint.po.Customer;
import com.epoint.service.CustomerService;
@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; // 模拟添加操作后系统突然出现异常
}
}
使用Spring的注解@Service来标识业务层的类,使用了@Transactional注解标识事务处理的类,通过@Autowired注解将CustomerMapper接口注入到类中。
5.5、applicationContext.xml中开启注解扫描
<!-- 开启扫描 -->
<context:component-scan base-package="com.epoint.service" />
5.6、整合测试
在DaoTest测试类中,添加测试方法transactionTest()。
@Test
public void transactionTest() {
ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
CustomerService customerService = act.getBean(CustomerService.class);
Customer customer = new Customer();
customer.setUsername("test");
customer.setJobs("manager");
customer.setPhone("9999999999");
customerService.addCustomer(customer);
}
运行,测试结果查看数据中测试数据是否插入成功。
参考书籍:Java EE企业级应用开发教程(Spring Spring MVC MyBatis)