目录
一、引言:
1.1、Spring的两大核心思想:
1.2 、Spring可以对mybatis提供哪些支持?
二、Spring整合mybatis准备工作:
2.1 创建maven工程
2.2 部署mybatis、Spring、整合依赖等框架
三、配置数据源(Druid连接池)
3.1 添加Druid依赖
3.2 创建Druid.properties属性文件
3.3 在ApplicationContext.xml配置数据源
四:配置sqlsessionFactory
五、配置MapperScannerConfigurer
六、整合Aop配置
6.1 将spring事务配置给spring容器
6.2 声明事务策略
6.2.1 事务的隔离级别
6.2.2 事务的传播机制
6.3 Aop事务配置
七、事务管理配置(注解配置)
八、案例测试
一、引言:
1.1 Spring的两大核心思想
1、IOC:控制反转,Spring容器可以完成对象的创建,属性的注入,对象管理等工作
2、Aop:面向切面,在不修改代码业务逻辑的情况下,实现原有的业务的增强
1.2 Spring可以对mybatis提供哪些支持?
1、Spring-Ioc可以为mybatis完成DataSource、SqlSessionFactory、SqlSession以及Dao对象的创建
2、Spring-Aop可以提供事物管理切面类完成对mybatis数据库中的事务管理
二、Spring整合mybatis准备工作:
2.1 创建maven工程
创建maven工程可以选择模板创建,也可以手动创建(建议手动创建),使用模板时间较慢,本实例中项目取名为“SpringMybatis02”(可以自定义),创建好项目后,补全项目框架结构,创建好的项目框架如下:
2.2 部署mybatis、Spring、整合依赖等框架
搭建好项目结构后,接下来进行jar包依赖的添加,分别是mysql驱动、mybatis依赖、spring-context、spring-Aspect、mybatis-spring(Spring整合mybatis的依赖)spring-jdbc也要添加进去,要不然进行数据源配置时会报错,依赖可以在maven仓库(https://mvnrepository.com)中进行查找,也可以赋值下面代码到pom.xml中进行添加
<!---添加mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<!---添加mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.19</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.19</version>
</dependency>
三、配置数据源(Druid连接池)
3.1 添加Druid依赖
这里的数据源我们使用的阿里巴巴旗下的Druid,如果想要其他的数据源,例如c3p0等,可以添加对应的jar包依赖即可,配置方法相同
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.9</version>
</dependency>
3.2 创建Druid.properties属性文件
外部属性文件中有数据源的相关配置,例如Driver、url、username、password等其他数据源的配置,具体如下:
druid.driver =com.mysql.jdbc.Driver
druid.url = jdbc:mysql://localhost:3306/spring_mybatis
druid.userName = root
druid.password = 990501
#初始化连接数
druid.pool.init=3
#高峰期过后,保留连接吃的个数
druid.pool.minIdle = 5
#高峰期,最大能创建连接的个数
druid.pool.MaxActive = 20
#等待的时间
durid.pool.timeout = 30
3.3 在ApplicationContext.xml配置数据源
在配置数据源之前,我们首先进行注解配置的声明以及使用<Context:property-placeholder>进行外部文件的引用,之后在使用<bean>标签进行数据源的配置,然后再使用${}符号记性属性值的注入即可;
<?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:Context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--声明使用注解配置-->
<Context:annotation-config/>
<!--声明Spring工厂注解的扫描范围-->
<Context:component-scan base-package="com.xgsm"/>
<!--引用外部文件-->
<Context:property-placeholder location="druid.properties"/>
<!--配置DruidDataSources-->
<bean id="DruidDataSources" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${druid.driver}"/>
<property name="url" value="${druid.url}"/>
<property name="username" value="${druid.userName}"/>
<property name="password" value="${druid.password}"/>
<property name="initialSize" value="${druid.pool.init}"/>
<property name="minIdle" value="${druid.pool.minIdle}"/>
<property name="maxActive" value="${druid.pool.MaxActive}"/>
<property name="maxWait" value="${durid.pool.timeout}"/>
</bean>
</beans>
加载驱动的时候这里要使用driverClassName,不能使用driver,要不然会报错!
四、配置sqlsessionFactory
首先需要依赖spring容器进行mybatis的sqlsessionfactory的创建,然后再进行数据源的配置,在配置sqlsessionFactory过程中可以对mapper映射文件进行配置,也可以进行配置需要定义的实体类别名、以及引入mybatis-config.xml(mybatis主配置文件)等操作~
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置数据源-->
<property name="dataSource" ref="DruidDataSources"/>
<!--配置mapper的路径-->
<property name="mapperLocations" value="classpath*:mappers/*Mapper.xml">
</property>
<!--配置需要定义别名的实体类的包-->
<property name="typeAliasesPackage" value="com.xgsm.pojo"/>
<!--配置需要mybatis的主配置文件-->
<property name="configLocation" value="Mybatis-config.xml"/>
</bean>
五、配置MapperScannerConfigurer:
在配置MapperScannerConfigurer中主要是加载dao包中的所有dao接口,通过sqlsessionFactory获取sqlsession,然后创建所有dao接口对象,存储在spring容器
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" >
<property name="sqlSessionFactoryBeanName" value="SqlsessionFactory"/>
<property name="basePackage" value="com.xgsm.Dao"/>
</bean>
六、整合Aop配置:
使用spring整合Aop配置,使用spring提供的事务管理切面类,完成dao中的CRUD操作的事务管理。步骤如下:
- 将spring提供的事务管理配置给spring
- 通过spring jdbc提供的<tx>标签,声明事物的管理策略(设置事务的隔离级别以及传播机制)
- 将事务管理策略以Aop配置,应用于Dao层的操作方法
6.1 将spring事务管理配置给spring
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="DruidDataSources"/>
</bean>
6.2 声明事务策略
通过Spring jdbc提供的<tx>标签声明事物的管理策略,并给事务设置隔离级别以及传播机制
<tx:advice id="TxAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="Insert*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<tx:method name="Update*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<tx:method name="Delete*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<tx:method name="Query*" isolation="REPEATABLE_READ" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
6.2.1 事务的隔离级别
事务的隔离级别就是约束两个事物是否可以并行,目的是保证数据的安全性,数据的隔离级别越高,数据的效率越低,具体的使用,要根据场景进行不同的选择,隔离级别有以下四种:
事务的隔离级别
隔离级别的分类: | 可能会造成的影响: |
Serializable(可序化):T1线程在执行过程中,T2线程既不能读也不能写(只能一个一个执行) | 最安全,但是效率是最低的 |
Repeatable read(可重复读):T1线程在执行过程中,T2线程能读但是不能写,T2可以添加数据 | 可能造成“幻读” |
Read Commit(读提交):T1线程在执行过程中,T2可以读也可以写,但是T1只能读取T2提交的数据 | 可能造成“幻读”、“不可重复读” |
Read UnCommit(读未提交):T1线程在执行过程中,T2可以读,也可以学,T1可以读取到T2未提交的数据 | 可能造成“幻读”、“不可重复读”、“脏读” |
6.2.2 事务的传播机制
事务的传播机制有七种,表示的是线程在执行过程中如何处理事务的,具体如下;
事务的传播机制
Required:如果上层方法没有事务,则创建一个新的事务;如果有,咋加入该事务。即必须在事务中执行 |
Supports:如果上层方法没有事务,则以非事务方式进行;如果有,咋加入该事务。即非必要在事务中执行 |
Required-new:如果上层方法没有事务,则创建一个新的事务;如果有,则将当前事物挂起。即必须在新事务中执行 |
Not-Supports:以非事务方式运行,如果已经存在事务,则挂起 |
Never:如果上层没有事务,则以非事务方式运行,如果已经存在事务,则抛出异常 |
ManadaTory:如果上层方法已经存在事务,则加入该事务,不存在则抛异常 |
Nested:如果上层没有事务,则创建新事务,如果有则嵌套在当前事务中执行 |
6.3 Aop事务配置
将事务管理策略以Aop配置,应用于Dao层的操作方法(主要是应用于ServiceI方法(ServiceImp)),使用<aop:config>标签;在标签内,定义切点。
<!--将事务管理以Aop配置,应用于ServiceI方法(ServiceImp)-->
<aop:config>
<aop:pointcut id="crud" expression="execution(* com.xgsm.Service.*.*(..))"/>
<aop:advisor advice-ref="TxAdvice" pointcut-ref="crud"/>
</aop:config>
七、事务管理配置(注解配置):
在配置文件中,配置事务管理类,使用<tx:annotation>声明使用注解方式进行事务配置,在需要进行事务管理的方法上添加注解,以下面例子为参考;
package com.xgsm.Service.ServiceImp;
import com.xgsm.Dao.UserDao;
import com.xgsm.Service.UserDaoService;
import com.xgsm.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Description: SpringMybatis
* Created by WuHuaSen .
* Created Date: 2022/4/17 17:06
* Version: V1.0
*/
@Service
public class UserDaoServiceImp implements UserDaoService {
@Autowired
private UserDao userDao;
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.SUPPORTS)
public List<User> SelectAllUser() {
return userDao.SelectAllUser();
}
}
九、案例测试:
Spring整合mybatis已经整合完毕,下面将通过一个实例进行整合测试,有这样一个数据库库,数据库中有两张表(User、ClassRoom),本实例中我们执行的操作是查询User表中的全部信息,进行打印输出,下面是具体的代码:
User实体类 | UserDao层 |
package com.xgsm.pojo;import lombok.*;@Data@ToString@NoArgsConstructor@AllArgsConstructor@Getter@Setterpublic class User { private int UserId; private String UserName; private String UserPwd; private String UserRealName; private String UserImg; private int ClazzId;} | package com.xgsm.Dao;import com.xgsm.pojo.User; import java.util.List; /** * Description: SpringMybatis02 * Created by WuHuaSen . * Created Date: 2022/4/19 15:34 * Version: V1.0 */ public interface UserDao { //查询所有学生 public List<User> SelectAllUser(); } |
本实例我们实现的service接口,具体代码如下:
UserDaoService 层 | UserDaoServiceImp 层 |
package com.xgsm.Service;import com.xgsm.pojo.User;import java.util.List;public interface UserDaoService { //查询所有学生 public List<User> SelectAllUser();} | package com.xgsm.Service.ServiceImp;import com.xgsm.Dao.UserDao;import com.xgsm.Service.UserDaoService;import com.xgsm.pojo.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Isolation;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import java.util.List;@Servicepublic class UserDaoServiceImp implements UserDaoService { @Autowired private UserDao userDao; public List<User> SelectAllUser() { return userDao.SelectAllUser(); }} |
mapper映射文件代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xgsm.Dao.UserDao">
<resultMap id="userMap" type="user">
<id column="user_id" property="UserId"></id>
<result column="user_name" property="UserName"></result>
<result column="user_pwd" property="UserPwd"></result>
<result column="user_realname" property="UserRealName"></result>
<result column="user_img" property="UserImg"></result>
<result column="clazz_id" property="ClazzId"></result>
<association property="classRoom" select="com.xgsm.dao.ClassRoomDao.SelectClassRoom" column=""></association>
</resultMap>
<sql id="user_cloumn_list">
user_id,user_name,user_pwd,user_realname,user_img,clazz_id
</sql>
<select id="SelectAllUser" resultMap="userMap">
SELECT <include refid="user_cloumn_list"/> FROM user;
</select>
</mapper>
测试类通过spring来接口获取对象,代码如下:
import com.xgsm.Service.UserDaoService;
import com.xgsm.pojo.User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class UserDaoTest {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
@Test
public void SelectAllUser() {
UserDaoService userDao = (UserDaoService) context.getBean("userDaoServiceImp");
List<User> users = userDao.SelectAllUser();
for (User i : users
) {
System.out.println(i);
}
}
}
测试结果:
在最后附上数据库文件以便读者进行测试:
CREATE DATABASE /*!32312 IF NOT EXISTS*/`spring_mybatis` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `spring_mybatis`;
/*Table structure for table `classroom` */
DROP TABLE IF EXISTS `classroom`;
CREATE TABLE `classroom` (
`clazz_id` int NOT NULL AUTO_INCREMENT,
`clazz_name` varchar(20) NOT NULL,
PRIMARY KEY (`clazz_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
insert into `classroom`(`clazz_id`,`clazz_name`) values (1,'java1833'),(2,'web1244');
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`user_id` int NOT NULL AUTO_INCREMENT,
`user_name` varchar(40) NOT NULL,
`user_pwd` varchar(40) NOT NULL,
`user_realname` varchar(40) NOT NULL,
`user_img` varchar(40) NOT NULL,
`clazz_id` int NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*Data for the table `user` */
insert into `user`(`user_id`,`user_name`,`user_pwd`,`user_realname`,`user_img`,`clazz_id`) values (1,'wangwu','111','王五','01.pdf',1),(2,'李四','222','李四','02.pdf',2),(3,'maliu','2355','马六','03.jpg',2),(4,'wangerniu','erere','王二妞','04.jpg',2);