Spring整合持久层
- Spring技术为什么要与持久层技术进行整合?
1、JavaEE开发过程中我们需要持久才能进行数据库的访问操作。
2、JDBC Hibernate MyBatis进行持久层过程中存在大量的代码冗余。
3、Spring基于模板设计模式对这些持久层技术呢作出了封装。
ps注释:
Spring基于模板设计模式对持久层框架封装之后呢,开发效率提升很多
- Spring能与哪些持久层技术进行整合呢?
目前所有的主流层持久层技术都能进行整合
JDBC:基于JDBCSpring提出了一个JDBCTemplate这样的一个类对JDBC进行了封装,这是它与JDBC的整合
Hibernate(JPA):基于HibernateSpring提出了HibernateTemplate这样的一个工具类对Hibernate进行了封装
MaBatis:基于Mybatis,Spring提供了SqlSessionFactoryBean MapperScannerConfigure这样的工具类简化Mybatis开发
Spring整合MyBatis
Spring整合Mybatis的本质在于Spring对于Mybatis的使用有不满意的地方,所以对Mybatis作出合理的封装,使持久层开发变得更加的简洁。
- Mybatis的开发过程(七步)
1、实体
2、实体别名
3、建立表
4、创建Dao接口
5、实现Mapper文件
6、注册Mapper文件
7、MybatisApi的调用
Mybatis开发存在的问题
配置繁琐,代码冗余
1、配置了使用别名,这样的配置文件就很繁琐,这样的配置大量出现。
2、所有的Mapper文件都需要注册到核心配置文件上。
3、Mybatis开发过程总Api调用过程中创建SqlSession对象的也很冗余
4、获取Mapper对象的时候也非常的冗余
Spring整合Mybatis整合思路分析
** Spring整合Mybatis的目的在于简化Mybatis开发,主要是从两个方面着手:
1、Spring对于创建SqlSessionFactory对象的创建过程做了一个封装,Spring提供了一个SqlSessionFactoryBean专门用于创建SqlSessionFactory对象,我们在Spring当中只需要在配置文件中进行响应的配置,将这个SqlSessionFactoryBean配置到Spring的核心配置文件当中,交由Spring工厂创建他的对象,经过这样的配置,这个对象就被创建出来,在创建这个类的时候,mybatis读取了一个Mybatis-config.xml的配置问价你,作为这个配置文件来讲,这个配置文件起的作用可以划分为三个环节,第一个是连接池的配置,第二个是类别名的配置,第三个是Sql文件的注册,Mybatis现在需要的这三块内容,在Spring当中通过注入的方式来提供给Mybatis,怎么来完成呢?这里个我们使用的依赖注入的方式,在bean标签当中通过Property标签,name属性是dataSource的属性、typeAliasesPackage、mapperLocations这三个属性,这样原有Mabatis核心配置文件中的三块 内容就通过注入的形式来注入到SqlSessionFactoryBean当中,然后可以为工厂对象创建提供材料,所以,Mybatis核心配置文件也就没有用了。那么这三个注入的三个属性是具体怎么实现的呢?连接池也是一个对象,dataSource是连接池对象,这里应该注入的是Spring整合的连接池对象的ref,引用这个而连接池对象之前需要把连接池对象创建出来,通过bean标签把连接池对象创建出来,连接池是一个用户自建的对象,我们使用Bean前创建好之后,把他进行注入即可。指定实体所对应的包就可以了,里边的实体类就Spring会我们自动创建别名,这个别名就是类名,这个属性在英勇过程中更加的强大,只需要指定包就可以了,对于这个Mapper注册,Spring整合Mybatis的时候MapperLocation当中采用了通配的设置,基于通配的方式例如:Mapper.xml就可以全部注册进去。
2、Spring对于创建代理对象的封装比较简单,提供了一个类MapperScannerConfigure这个类,他需要两个要素,一个是SqlSessionFactory对象,一个是Dao层的Class对象,在Bean当中,把SqlSessionFactoryBean注入进去就可以拿到工厂对象,另一个就是Dao接口的class对象,我们指定basePackage的属性,执行这个包名,就可以生成对于Dao的实现类的对象,最终通过这个MapperScannerConfigure这个类就可以创建Dao的实现类的对象,我们这个工具类当中创建的Dao实现类的对象,他们的id值是接口首单词首字母小写。*
Spring与Mybatis整合的开发步骤
配置原理
**1、配置文件:applicationContext.xml文件的配置
第一步:配置创建SqlSessionFactroy
在这一步当中,我们为了获取这个对象,就需要配置Spring为我们准备的SqlSessionFactoryBean这个类,配置好这个类之后呢就可以获取到SqlSessionFactory这个对象了,我们在Spring核心配置文件当中配置这个类的对象的时候,需要首先创建dataSource数据源的Bean的标签,创建他的对象,然后将这个对象使用Property标签引入到,SqlSessionFactoryBean的对象的创建中,然后需要配置类别名,这个也是对应一个Property标签中的一个typeAliasesPackage属性,在这个属性当中指定实体类所在的包,通过这个配置,以后我们的实体Bean只要是放到这个包中,那么在以后的Mybatis映射中,他的别名就叫做他的类名。然后第三个需要注入的属性是配置文件或者映射文件的路径通用配置等,将来我们的Mapper文件将会放到一个特定的目录里,我们一方面制定了这个目录对应的路径信息,另一方面,我们使用一种通配的方式来适配所有的Mapper文件(com.dashu.mapper/*Mapper.xml),这样就可以将所有的Mapper文件被Spring感知到,并将他们配置到SqlSessionFactory对象当中。这几块的配置极大地简化了开发。
第二步:配置创建DAO接口的实现类
为了实现这个第二部,Spring当中准备了一个MapperScannerConfigure这样的类,作为这个类,他主要的作用是通过session.getMapper()方法获取xxxDao实现类的对象,他这个实现类的XXXDao 实现类的id值是xXXDao,在这个对象当中他需要获取Session对象,通过Session对象获取这个类的dao实现类的对象。所以,在MapperScannerConfigure的Bean标签当中应该将SqlSessionFactoryBean的对象的id值赋值给MapperScannerConfigure的sqlSessionFactoryBeanName属性,按照这个配置就可以找到SqlSessionFactoryBean这个对象,另外一个属性basePacakge指定的是放置Dao的具体的包,Spring通过扫描这个包创建包下所有的Dao的实现类。
总结:
以上的这两种配置的好处在于,只需要配置一次,以后所有的都不需要进行重新配置。
**
开发过程
1、实体Bean
2、表
3、创建Dao接口
4、实现Mapper文件
总结:这才是未来实战中写的代码。
- 搭建开发环境
所谓的搭建开发环境指的就是引入Jar包
<?xml version="1.0" encoding="UTF-8"?> <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.dashu</groupId> <artifactId>spring-mybatis</artifactId> <version>V1.0.1</version> <dependencies> <!--引入druid数据源,这是一个连接池。--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.18</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--Spring对Jdbc封装--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.14.RELEASE</version> </dependency> <!--这个是Spring和mybatis整合的JAR包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> </dependencies> </project>
- Spring配置文件的配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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.xsd"> <!--连接池--> <!--我们使用连接池的本质就是为了创建和数据库的链接。--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/tree?useSSL=false"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!--创建SqlSessionFactroyBean对象--> <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="typeAliasesPackage" value="com.dashu.entity"/> <property name="mapperLocations"> <list> <!--这是Spring里边内置的关键字代表Classes目录,也就是java目录--> <!--/旁边是路径名,/右边是命名规范。--> <value>classpath:com.dashu.mapper/*Mapper.xml</value> </list> </property> </bean> <!--创建Dao对象--> <bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/> <property name="basePackage" value="com.dashu.dao"/> </bean> </beans>
- 编码
package com.dashu.Dao; import com.dashu.entity.User; /** * @Auther: DaShu * @Date: 2021/7/26 20:29 * @Description: */ public interface UserDao { public void save(User user); }
package com.dashu.test; import com.dashu.Dao.UserDao; import com.dashu.entity.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @Auther: DaShu * @Date: 2021/7/26 20:47 * @Description: */ public class TestMybatisSpring { @Test public void test1(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); UserDao userDao =(UserDao) ctx.getBean("userDao"); User user = new User(); user.setAge(16); user.setName("liming"); userDao.save(user); } }
Spring整合Mybatis细节
2021-07-26 20:58:12 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@66d33a 2021-07-26 20:58:13 DEBUG XmlBeanDefinitionReader:396 - Loaded 3 bean definitions from class path resource [applicationContext.xml] 2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'scanner' 2021-07-26 20:58:13 DEBUG LogFactory:135 - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. 2021-07-26 20:58:13 DEBUG ClassPathMapperScanner:437 - Identified candidate component class: file [D:\giteesource\jdbc\spring-mybatis\target\classes\com\dashu\dao\UserDao.class] 2021-07-26 20:58:13 DEBUG ClassPathMapperScanner:49 - Creating MapperFactoryBean with name 'userDao' and 'com.dashu.Dao.UserDao' mapperInterface 2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSource' 2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'sqlSessionFactoryBean' 2021-07-26 20:58:13 DEBUG SqlSessionFactoryBean:49 - Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration 2021-07-26 20:58:13 DEBUG SqlSessionFactoryBean:49 - Parsed mapper file: 'file [D:\giteesource\jdbc\spring-mybatis\target\classes\com.dashu.mapper\UserDaoMapper.xml]' 2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userDao' 2021-07-26 20:58:13 DEBUG SqlSessionUtils:49 - Creating a new SqlSession 2021-07-26 20:58:13 DEBUG SqlSessionUtils:49 - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@152aa092] was not registered for synchronization because synchronization is not active 2021-07-26 20:58:13 DEBUG DataSourceUtils:115 - Fetching JDBC Connection from DataSource 2021-07-26 20:58:14 INFO DruidDataSource:1003 - {dataSource-1} inited 2021-07-26 20:58:14 DEBUG SpringManagedTransaction:49 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@25fb8912] will not be managed by Spring 2021-07-26 20:58:14 DEBUG save:159 - ==> Preparing: Insert into tree (name,age) values (?,?) 2021-07-26 20:58:14 DEBUG save:159 - ==> Parameters: liming(String), 16(Integer) 2021-07-26 20:58:14 DEBUG save:159 - <== Updates: 1 2021-07-26 20:58:14 DEBUG SqlSessionUtils:49 - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@152aa092]
1、单纯使用Mybatis进行开发的时候,我们一定会手动记性提交事务,在代码sql执行完毕之后,会有一个session.commit()来提交事务,但是现在使用Spring整合Mybatis之后,并没有在代码中体现事务提交, 这个Dao对象由Spring来为我们进行创建的时候,我们并没有手动提交事务,为什么数据可以插入到数据库当中呢?Connection对象是链接对象,连接对象控制着事务,谁控制着连接对象就变相控制着事务,在整个Spring整合Mybatis之后是谁控制着链接对象呢?在刚才的运行日志中,链接对象并不是交由Spring进行管理,那不是Spring就是Mybatis,本质上控制Connection对象,是连接池对象,当我们使用单纯Mybatis进行开发的时候,Mybatis提供的连接池对象创建链接,Spring和Mybatis整合之后,我们使用的是Druid连接池,他负责Connection对象的创建,这样使用和当时Mybatis提供连接池创建链接对象,有着细微的差别,Mybatis使用自身连接池创建对象之后,调用了一个Connection.setAutoCommit(false),这样就把链接对象中的事务控制改为了手动,这样在操作完成之后,必须手工提交,这就是在Mybatis原生开发的时候必须手动提交,而使用Druid连接池的时候,Connection.setAutoCommit(true)这是默认值,意味着保持着自动控制事务,就是完成一条SQL操作就会自动提交事务,所以,我们使用了Druid链接池之后,是自动提交事务,不需要手动提交。日后换成了其他的连接池之后,都一样,他们的都是true,都是自动提交事务,一条SQL语句都会自动的提交。
答案:Spring和Mybatis整合时引入外部连接池,,保持着自动提交事务的机制(Connection.setaAutoCommit(true)不需要手动提交事务)
注意:
未来实战中,我们设计到多条SQL提交,我们需要把多条SQL设置成一个整体,手工控制成一个事务(Sql一起成功,一起失败),将来呢在Spring当中,Spring会通过他的事务控制,解决这个问题
Spring事务处理
什么是事务?
保证业务操作完整性的数据库操作,就是数据库中的操作要么一起成功要么 一起失败,而且不能产生响应的影响,事务这个概念是数据库的范畴,我们通过Java代码只是完成对这种机制的调用。
事务的ACID
1、原子性:一起成功一起失败
2、一致性:与实际发生相一致
3、隔离性:事务之间不可以相互访问
4、持久性:持久到数据库
如何来控制事务
这里我们先不考虑Spring
JDBC控制事务
Connection.setAutoCommit(false)开启事务
ConnectIon.commit()提交事务
Connection,rollback()回滚事务
其核心就是控制Connection链接对象来控制事务
Mybatis控制事务
Mybatis自动开启事务
sqlSession.commit()提交事务
sqlSession.rollback()回滚事务
总结:开启-提交-回滚
Mybatis底层的SqlSession底层也是封装的Connection,底层也是调用的是Connection.commit,不论是当前的jdbc还是Mybatis当中的sqlSession还是将来的jta,底层都是调用的Connection.commit,封装的都是COnnection对象,所有的技术,我们看到
的表象是不一样的,但是底层都是一样的,以上的都是不讨论Spring的事务控制的前提下。
Spring控制事务开发
开发步骤
事务是业务开发过程中的额外功能,因为是额外功能所以我们可以采用Aop的方式来进行开发,Spring当中的事务是通过Aop的方式来进行控制事务开发的
1、原始对象
(1)这里的原始对象就是XXXUserServiceImpl中的方法,核心功能(业务功能+Dao的调用)
(2)我们要把Dao作为Service的成员边量,通过Spring的方式进行依赖注入的方式进行赋值,并为他提供get,set方法。
2、额外功能
(1)第一种实现MethodInterceptor,在里面的invoke方法中调用原始对象原始方法,并进行额外功能编写,如果原始方法抛出异常,我们就进行事务的回滚。
(2)@Aspect @Around这种方式呢实现原理是一样的,我们可以把开启提交回滚的代码写在额外功能当中,所以Spring也会写,所以呢,Spring框架就直接把这个代码给写了,给分装好了,我们直接用即可,那我们在org.springframework.jdbc.datasourceDataSourceTransactionManager这里边把这个给封装好了,这里边就是事务控制的额外功能,只需要用好这个类就行,要想这个类起作用,就需要在额外功能中对这个连接对象的支持和配合,所以说DataSourceTranSactionManager依赖连接对象,我们需要给她注入连接,但是我们现在引入了连接池,现在呢连接来自于连接池,所以把连接池注入给她即可,这样这个类就可以基于连接池对象完成对事物的控制。在这里我们需要注意两个要点,第一个代码不用我们写了,Spring已经帮我们写好了,第二个要点,我们是用Spring进行实物控制的时候需要为这个类注入连接池对象,有了连接池对象就等效于有了链接,就可以控制事务了。
3、切入点
@Transactionl就可以控制事务了
应用这个注解就可以给业务方法加入事务控制了。
1、类上:类中所有方法都会加入事务
2、方法上:这个方法会加入事务
4、组装切面
切面一定是有两个部分组成的,
1、切入点
2、额外功能
在Spring进行实物控制的时候,他的组装切面的时候是通过标签来控制的,在标签当中会体现这两个元素。
<tx:annotation-driven transaction-manager=“”/>这个属性适用于获取额外功能,切入点他自己会直接 扫描注解来组装注解信息,引入这个标签我们就组装好了事务的切面。
Spring控制事务的编码
搭建开发环境
引入响应的jar包,Spring引入事务控制的时候,他有开发了一个jar包需要我们引入进来,Spring-tx,引入这个jar包就把Spring与事务整合的Jar包引入了进来。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.1.14.RELEASE</version> </dependency>
原始对象和切入点
package com.dashu.service; import com.dashu.Dao.UserDao; import com.dashu.entity.User; import org.springframework.transaction.annotation.Transactional; /** * @Auther: DaShu * @Date: 2021/7/26 22:36 * @Description: */ /*定义切入点*/ @Transactional public class UserServiceImpl implements UserService{ private UserDao userDao; public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void register(User user) { userDao.save(user); } }
额外功能和切面组装
<!--DataSourceTransactionManager--> <bean id="dataSourceTransactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--组装事物切面,选择Tx结尾的。--> <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
测试Spring事务处理
@Test public void test2(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); UserService userService = (UserService) ctx.getBean("userService"); User user = new User(); user.setName("张晓哎"); user.setAge(21); userService.register(user); }
测试结果打印
2021-07-26 22:54:34 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@66d33a 2021-07-26 22:54:34 DEBUG XmlBeanDefinitionReader:396 - Loaded 10 bean definitions from class path resource [applicationContext.xml] 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'scanner' 2021-07-26 22:54:34 DEBUG LogFactory:135 - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. 2021-07-26 22:54:34 DEBUG ClassPathMapperScanner:437 - Identified candidate component class: file [D:\giteesource\jdbc\spring-mybatis\target\classes\com\dashu\dao\UserDao.class] 2021-07-26 22:54:34 DEBUG ClassPathMapperScanner:49 - Creating MapperFactoryBean with name 'userDao' and 'com.dashu.Dao.UserDao' mapperInterface 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionalEventListenerFactory' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSource' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' 2021-07-26 22:54:34 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'sqlSessionFactoryBean' 2021-07-26 22:54:34 DEBUG SqlSessionFactoryBean:49 - Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration 2021-07-26 22:54:35 DEBUG SqlSessionFactoryBean:49 - Parsed mapper file: 'file [D:\giteesource\jdbc\spring-mybatis\target\classes\com.dashu.mapper\UserDaoMapper.xml]' 2021-07-26 22:54:35 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userService' 2021-07-26 22:54:35 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userDao' 2021-07-26 22:54:35 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSourceTransactionManager' 2021-07-26 22:54:35 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' 2021-07-26 22:54:35 DEBUG DataSourceTransactionManager:372 - Creating new transaction with name [com.dashu.service.UserServiceImpl.register]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 2021-07-26 22:54:35 INFO DruidDataSource:1003 - {dataSource-1} inited 2021-07-26 22:54:35 DEBUG DataSourceTransactionManager:265 - Acquired Connection [com.mysql.jdbc.JDBC4Connection@273444fe] for JDBC transaction 2021-07-26 22:54:35 DEBUG DataSourceTransactionManager:282 - Switching JDBC Connection [com.mysql.jdbc.JDBC4Connection@273444fe] to manual commit 2021-07-26 22:54:35 DEBUG SqlSessionUtils:49 - Creating a new SqlSession 2021-07-26 22:54:35 DEBUG SqlSessionUtils:49 - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1972e513] 2021-07-26 22:54:35 DEBUG SpringManagedTransaction:49 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@273444fe] will be managed by Spring 2021-07-26 22:54:35 DEBUG save:159 - ==> Preparing: Insert into tree (name,age) values (?,?) 2021-07-26 22:54:35 DEBUG save:159 - ==> Parameters: 张晓哎(String), 21(Integer) 2021-07-26 22:54:35 DEBUG save:159 - <== Updates: 1 2021-07-26 22:54:35 DEBUG SqlSessionUtils:49 - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1972e513] 2021-07-26 22:54:35 DEBUG SqlSessionUtils:49 - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1972e513] 2021-07-26 22:54:35 DEBUG SqlSessionUtils:49 - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1972e513] 2021-07-26 22:54:35 DEBUG SqlSessionUtils:49 - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1972e513] 2021-07-26 22:54:35 DEBUG DataSourceTransactionManager:743 - Initiating transaction commit 2021-07-26 22:54:35 DEBUG DataSourceTransactionManager:327 - Committing JDBC transaction on Connection [com.mysql.jdbc.JDBC4Connection@273444fe] 2021-07-26 22:54:36 DEBUG DataSourceTransactionManager:385 - Releasing JDBC Connection [com.mysql.jdbc.JDBC4Connection@273444fe] after transaction
事务编码细节
1、上述测试实例并不能证明事务加进来了,因为原有逻辑可以完成插入操作的,事务加上没有一定是加上了,以下是验证细节
package com.dashu.service; import com.dashu.Dao.UserDao; import com.dashu.entity.User; import org.springframework.transaction.annotation.Transactional; /** * @Auther: DaShu * @Date: 2021/7/26 22:36 * @Description: */ /*定义切入点*/ @Transactional public class UserServiceImpl implements UserService{ private UserDao userDao; public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void register(User user) { userDao.save(user); throw new RuntimeException("测试异常"); } }
D:\DevelopPackage\jdk8\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar=58943:D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\bin" -Dfile.encoding=UTF-8 -classpath "D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar;D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\plugins\junit\lib\junit5-rt.jar;D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\plugins\junit\lib\junit-rt.jar;D:\DevelopPackage\jdk8\jre\lib\charsets.jar;D:\DevelopPackage\jdk8\jre\lib\deploy.jar;D:\DevelopPackage\jdk8\jre\lib\ext\access-bridge-64.jar;D:\DevelopPackage\jdk8\jre\lib\ext\cldrdata.jar;D:\DevelopPackage\jdk8\jre\lib\ext\dnsns.jar;D:\DevelopPackage\jdk8\jre\lib\ext\jaccess.jar;D:\DevelopPackage\jdk8\jre\lib\ext\jfxrt.jar;D:\DevelopPackage\jdk8\jre\lib\ext\localedata.jar;D:\DevelopPackage\jdk8\jre\lib\ext\nashorn.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunec.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunjce_provider.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunmscapi.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunpkcs11.jar;D:\DevelopPackage\jdk8\jre\lib\ext\zipfs.jar;D:\DevelopPackage\jdk8\jre\lib\javaws.jar;D:\DevelopPackage\jdk8\jre\lib\jce.jar;D:\DevelopPackage\jdk8\jre\lib\jfr.jar;D:\DevelopPackage\jdk8\jre\lib\jfxswt.jar;D:\DevelopPackage\jdk8\jre\lib\jsse.jar;D:\DevelopPackage\jdk8\jre\lib\management-agent.jar;D:\DevelopPackage\jdk8\jre\lib\plugin.jar;D:\DevelopPackage\jdk8\jre\lib\resources.jar;D:\DevelopPackage\jdk8\jre\lib\rt.jar;D:\giteesource\jdbc\spring-mybatis\target\classes;D:\DevelopPackage\repository\junit\junit\4.12\junit-4.12.jar;D:\DevelopPackage\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\DevelopPackage\repository\com\alibaba\druid\1.1.18\druid-1.1.18.jar;D:\DevelopPackage\repository\mysql\mysql-connector-java\5.1.48\mysql-connector-java-5.1.48.jar;D:\DevelopPackage\repository\org\mybatis\mybatis\3.4.6\mybatis-3.4.6.jar;D:\DevelopPackage\repository\org\springframework\spring-jdbc\5.1.14.RELEASE\spring-jdbc-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-beans\5.1.14.RELEASE\spring-beans-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-core\5.1.14.RELEASE\spring-core-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-jcl\5.1.14.RELEASE\spring-jcl-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-tx\5.1.14.RELEASE\spring-tx-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-context\5.1.4.RELEASE\spring-context-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-aop\5.1.4.RELEASE\spring-aop-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-expression\5.1.4.RELEASE\spring-expression-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\mybatis\mybatis-spring\2.0.2\mybatis-spring-2.0.2.jar;D:\DevelopPackage\repository\org\slf4j\slf4j-log4j12\1.7.25\slf4j-log4j12-1.7.25.jar;D:\DevelopPackage\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;D:\DevelopPackage\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.dashu.test.TestMybatisSpring,test2 2021-07-26 23:00:29 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@66d33a 2021-07-26 23:00:29 DEBUG XmlBeanDefinitionReader:396 - Loaded 10 bean definitions from class path resource [applicationContext.xml] 2021-07-26 23:00:29 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'scanner' 2021-07-26 23:00:29 DEBUG LogFactory:135 - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. 2021-07-26 23:00:29 DEBUG ClassPathMapperScanner:437 - Identified candidate component class: file [D:\giteesource\jdbc\spring-mybatis\target\classes\com\dashu\dao\UserDao.class] 2021-07-26 23:00:29 DEBUG ClassPathMapperScanner:49 - Creating MapperFactoryBean with name 'userDao' and 'com.dashu.Dao.UserDao' mapperInterface 2021-07-26 23:00:29 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 2021-07-26 23:00:29 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 2021-07-26 23:00:29 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionalEventListenerFactory' 2021-07-26 23:00:29 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSource' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'sqlSessionFactoryBean' 2021-07-26 23:00:30 DEBUG SqlSessionFactoryBean:49 - Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration 2021-07-26 23:00:30 DEBUG SqlSessionFactoryBean:49 - Parsed mapper file: 'file [D:\giteesource\jdbc\spring-mybatis\target\classes\com.dashu.mapper\UserDaoMapper.xml]' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userService' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userDao' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSourceTransactionManager' 2021-07-26 23:00:30 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' 2021-07-26 23:00:30 DEBUG DataSourceTransactionManager:372 - Creating new transaction with name [com.dashu.service.UserServiceImpl.register]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 2021-07-26 23:00:30 INFO DruidDataSource:1003 - {dataSource-1} inited 2021-07-26 23:00:31 DEBUG DataSourceTransactionManager:265 - Acquired Connection [com.mysql.jdbc.JDBC4Connection@273444fe] for JDBC transaction 2021-07-26 23:00:31 DEBUG DataSourceTransactionManager:282 - Switching JDBC Connection [com.mysql.jdbc.JDBC4Connection@273444fe] to manual commit 2021-07-26 23:00:31 DEBUG SqlSessionUtils:49 - Creating a new SqlSession 2021-07-26 23:00:31 DEBUG SqlSessionUtils:49 - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1972e513] 2021-07-26 23:00:31 DEBUG SpringManagedTransaction:49 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@273444fe] will be managed by Spring 2021-07-26 23:00:31 DEBUG save:159 - ==> Preparing: Insert into tree (name,age) values (?,?) 2021-07-26 23:00:31 DEBUG save:159 - ==> Parameters: xi(String), 21(Integer) 2021-07-26 23:00:31 DEBUG save:159 - <== Updates: 1 2021-07-26 23:00:31 DEBUG SqlSessionUtils:49 - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1972e513] 2021-07-26 23:00:31 DEBUG SqlSessionUtils:49 - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1972e513] 2021-07-26 23:00:31 DEBUG SqlSessionUtils:49 - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1972e513] 2021-07-26 23:00:31 DEBUG DataSourceTransactionManager:836 - Initiating transaction rollback 2021-07-26 23:00:31 DEBUG DataSourceTransactionManager:342 - Rolling back JDBC transaction on Connection [com.mysql.jdbc.JDBC4Connection@273444fe] 2021-07-26 23:00:31 DEBUG DataSourceTransactionManager:385 - Releasing JDBC Connection [com.mysql.jdbc.JDBC4Connection@273444fe] after transaction java.lang.RuntimeException: 测试异常 at com.dashu.service.UserServiceImpl.register(UserServiceImpl.java:28) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy18.register(Unknown Source) at com.dashu.test.TestMybatisSpring.test2(TestMybatisSpring.java:35) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53) Process finished with exit code -1
第二个细节,是 --proxy-target-class="false"这是默认属性,默认是false,可以设置成true,设置成true就是使用cglib动态代理。
<tx:annotation-driven transaction-manager=“dataSourceTransactionManager” proxy-target-class=“false”/>完成动态代理底层的切换。
Spring的事务属性
什么是事务属性
什么是属性:描述物体特征的一系列值,描述特征的值有差异,所以就有好看不好看的概念,事务的属性和事务的特征就是描述事务特征的一系列值
1、隔离属性
2、传播属性
3、只读属性
4、超时属性
5、异常属性
如何添加事务属性
我们在开发过程中添加上这些事务的属性就可以控制事务的特征
@Transactionnal(isoLation=,propagation=,readOnly=,timeout=,rollbackFor,NoRollbackFor=)用于描述传播属性)这个注解就可以用来配置属性。
事务属性详解
1、隔离属性
**概念:描述了事务解决并发问题的特征
1、什么是并发?
多个事务(用户)同一时间访问操作了相同的数据。
例如:一张表中有四条数据,有一个事务1访问了第一行数据,第二个事务同事也访问了第一行数据,这样就产生了并发问题。同一时间、同一数据。同一时间也是有一个微小前后的差异
2、并发会产生什么问题?
(1)脏读
(2)不可重复读
(3)幻读
3、并发问题如何解决?
实际上及时隔离属性和对应的值解决的工作。我们在隔离属性中设置不同的值解决并发处理过程中的问题,在事务属性的概念中,并发会产生问题,并发的问题可以通过隔离属性来进行解决。
**
- 脏读
概念:一个事务读取了另一个事物当中没有提交的数据。另一个事物一回滚数据就错了。产生这个问题的核心就是读取了事务没有提交的数据,前者一回滚,后者就凉凉。
解决方案:@Transactional(isolation=Isolation.READ_COMMIT)读已提交的数据,这样就可以避免脏读的产生。
@Transactional(isolation = Isolation.READ_COMMITTED)
- 不可重复读
概念:一个事务中多次获取相同的数据,但是获取每次的结果不一致
例如:A开始事务查询某一行数据,获取到第一次的值,B开始一次事务update一次,然后快速提交事务,A操作完其他行数据过来又查了一遍,成了800;这就是不可重复读。在A的操作过程中出现了数据不一致的情况。不可重复读获取到的不是事务未提交的脏数据,这些数据已经提交了,不可能被回滚了,一个事务中对一组数据只进行了查询,本来今天查一次1000,明天查一次800这样很正常,只不过在今天的一次事务中就读取到了不一致, 结果就有点尴尬,这样后续处理的时候就不知道以哪个值为基准了,这样就是不可重复读的危害,不可重复读不是脏读,他读取的事已经提交的数据,她是在一个事务中发生的这样的情况。解决方案:@Transactional(isolation = Isolation.REPEATABLE_READ),我们加上这样代码之后数据库会为我们操作的这几行数据加上一把行锁。他的底层本质就是一把行锁。这样只有等第一个事务提交之后,第二个事务才能获取到这个行锁进行操作这个数据。
本质:一把行锁
@Transactional(isolation = Isolation.REPEATABLE_READ)
- 幻影读
概念:一个事物中多次对整表进行查询统计,但是结果不一样,会产生本事务中数据不一致的问题。
关键字:整表操作:例如Count(balance),结果不一样。
解决方案:@Transactional(isolation = Isolation.SERIALIZABLE)
本质:表锁
@Transactional(isolation = Isolation.SERIALIZABLE)
事务隔离属性的总结
并发安全:@Transactional(isolation = Isolation.SERIALIZABLE)最安全,锁住所有的表,别人用表中数据的时候只能等着,并发安全最高,另外是@Transactional(isolation = Isolation.REPEATABLE_READ)他是为数据添加了行锁,别人操作这一行的时候,别人别搞,最差的是@Transactional(isolation = Isolation.READ_COMMITTED),这个只要求读取别人提交之后的数据,而没有添加任何额外限制,并发安全最低。
运行效率:整好反过来。
数据库对于隔离属性的支持
并不是所有的数据库对以上四个属性都支持
Oracle不支持这个值,是如何解决不可重复读的呢?他没有采用隔离属性的方式来解决,而是采用多版本比对的方式来解决不可重复读的问题。
默认的隔离属性:如果程序员不指定隔离属性的话Spring会指定默认的隔离属性,Isolation-default这是Spring默认帮我们设置的,表达的含义是调用不同数据库所设置的默认隔离属性,对应Mysql和Oracle就是如下的值:。
MySql是:Isolation.REPEATABLE_READ
Oracle是:Isolation.READ_COMMITTED
隔离属性在实战中的建议
隔离属性实战过程中,我们推荐使用Spring的默认值ISOLATION_DEFAULT,为什么推荐使用这个?不用写,未来的实战过程中,并发访问的情况本身就很低,必须有一个前提:海量用户,并发可能性很低,为了可能遇到问题直接加表锁,这样是很不合理的。如果真的遇到这种并发问题了,我们有限推荐的方案也不是隔离属性来解决,而是采用乐观锁的方式,乐观锁是应用锁,不会过多影响我们的效率,隔离属性是物理锁,物理锁对效率影响比较大。Hibernate(JPA) 通过Version的方式进行控制乐观锁,Mybatis中默认没有支持乐观锁,对于乐观锁的控制比较繁琐,需要定义Mybatis当中的拦截器进行自定义开发,在整个隔离属性的开发过程中,我们还是要优先保证效率,我们使用他默认的就行了。一旦遇到了并发问题,我们可以通过乐观锁的方式进行解决。
2、传播属性
概念:描述了事务解决嵌套问题的特征
事务的嵌套:事务之间的包含的关系,一个大事务之间包含一个或若干个小事务,这就是事务的嵌套的问题
事务的嵌套
什么场景会出现事务嵌套呢?
service调用Service会出现事务嵌套的
一旦出现了事务嵌套之后,会出现什么问题呢?
正常情况下是没有问题的,一旦C当中出现了异常,进行了回滚,那么C在A当中,C回滚,A也会回滚,此时A回滚了,C回滚了,但是B已经提交了,事务之间相互影响,违反原子性了。
传播属性的值及其用法
通过设置合理的事务属性之后,彼此之间就不存在事务的嵌套了。这样的话就实现了事务的原子性。他这个事务的传播属性搞定的就是同一时间只有一个事务属性在,没有嵌套的发生,只有最外层事务的存在。实际的开发过程中也就是通过注解属性的形式进行。REQUIRED这个属性经常用在增删改操作中,Supports这个属性值,经常用到查询的操作当中。
默认的传播属性
也就是说程序员不手动进行设置传播属性的话,Spring会默认为我们设置传播属性,默认值对应的值是PROPAGATION_REQUIRED,这个是传播属性的默认值,这个适用于增删改,查询的话,我们推荐Supports
建议:增删改方法:我们使用默认值就可以了(PROPAGATION_REQUIRED)
查询操作:我们显示的指定传播属性值为SUPPORTSREQUIRES_NEW:挂起外部事务,创建新的事务,的含义就是外部事物先暂停,内部事务开启执行提交,内部事务完成之后,在进行外部事务适用于在日志操做中,不管外部成功与否,否要把正常日志异常日志插入到数据库中
挂起外部事务,就是外部事务先暂停,先被挂起,内部业务并没有融合到外部事务中,仅仅执行而已,执行完毕之后在激活外部事务。
NOT_SUPPORTED 外部存在事务时挂起外部事务,执行内部逻辑,内部逻辑执行完毕之后,激活外部事物
其他两个:略
3、只读属性
**作用:针对于值进行查询操作的方法,我们可以加入这个只读属性,可以提高运行效率。确定了这个方法是只有查询,那么加上这个属性之后,就不会加上任何的锁了,查询效率就会变很高。
我们在类上加入@Transaction这个注解之后,全部方法都开启了事务,查询方法也开启了事务,对于Mysql来讲默认的隔离性是:Isolation.REPEATABLE_READ这个本质是行锁,那么在这个方法再次引入@Transaction这个注解之后,我们可以指定只读属性来覆盖类上的默认设定,这样的话查询的时候不用加锁,提高效率。
只读属性默认值:false
**
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true) public void login(String name,String password){ }
4、超时属性
概念:指定了了事务等待的最长时间
为什么事务需要等待呢?
某个用户访问某张表的第一行数据,加了一把行锁,第二个用户也发起对这一行数据的访问,那么第二个用户就需要进行等待,第二个用户最多可以等待多长时间呢?就是通过这个超时属性来设置的
等待的时间是以秒为单位,超时之后就会抛出超时异常。
如何进行应用呢?
超时属性默认值 -1 最终由对应的数据库来指定,每个数据库的产品都默认设置了这些值。
package com.dashu.service; import com.dashu.Dao.UserDao; import com.dashu.entity.User; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * @Auther: DaShu * @Date: 2021/7/26 22:36 * @Description: */ /*定义切入点*/ @Transactional(timeout = 2) public class UserServiceImpl implements UserService{ private UserDao userDao; public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void register(User user) throws InterruptedException { Thread.currentThread().sleep(3000); userDao.save(user); throw new RuntimeException("测试异常"); } @Transactional(propagation = Propagation.SUPPORTS,readOnly = true) public void login(String name,String password){ } }
2021-07-27 21:48:45 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@66d33a 2021-07-27 21:48:45 DEBUG XmlBeanDefinitionReader:396 - Loaded 10 bean definitions from class path resource [applicationContext.xml] 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'scanner' 2021-07-27 21:48:46 DEBUG LogFactory:135 - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. 2021-07-27 21:48:46 DEBUG ClassPathMapperScanner:437 - Identified candidate component class: file [D:\giteesource\jdbc\spring-mybatis\target\classes\com\dashu\dao\UserDao.class] 2021-07-27 21:48:46 DEBUG ClassPathMapperScanner:49 - Creating MapperFactoryBean with name 'userDao' and 'com.dashu.Dao.UserDao' mapperInterface 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionalEventListenerFactory' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSource' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' 2021-07-27 21:48:46 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'sqlSessionFactoryBean' 2021-07-27 21:48:46 DEBUG SqlSessionFactoryBean:49 - Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration 2021-07-27 21:48:47 DEBUG SqlSessionFactoryBean:49 - Parsed mapper file: 'file [D:\giteesource\jdbc\spring-mybatis\target\classes\com.dashu.mapper\UserDaoMapper.xml]' 2021-07-27 21:48:47 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userService' 2021-07-27 21:48:47 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userDao' 2021-07-27 21:48:47 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSourceTransactionManager' 2021-07-27 21:48:47 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' 2021-07-27 21:48:47 DEBUG DataSourceTransactionManager:372 - Creating new transaction with name [com.dashu.service.UserServiceImpl.register]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_2 2021-07-27 21:48:47 INFO DruidDataSource:1003 - {dataSource-1} inited 2021-07-27 21:48:48 DEBUG DataSourceTransactionManager:265 - Acquired Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] for JDBC transaction 2021-07-27 21:48:48 DEBUG DataSourceTransactionManager:282 - Switching JDBC Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] to manual commit 2021-07-27 21:48:51 DEBUG SqlSessionUtils:49 - Creating a new SqlSession 2021-07-27 21:48:51 DEBUG SqlSessionUtils:49 - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35841320] 2021-07-27 21:48:51 DEBUG SpringManagedTransaction:49 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] will be managed by Spring 2021-07-27 21:48:51 DEBUG SqlSessionUtils:49 - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35841320] 2021-07-27 21:48:51 DEBUG SqlSessionUtils:49 - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35841320] 2021-07-27 21:48:51 DEBUG SqlSessionUtils:49 - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35841320] 2021-07-27 21:48:51 DEBUG DataSourceTransactionManager:836 - Initiating transaction rollback 2021-07-27 21:48:51 DEBUG DataSourceTransactionManager:342 - Rolling back JDBC transaction on Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] 2021-07-27 21:48:51 DEBUG DataSourceTransactionManager:385 - Releasing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] after transaction org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Tue Jul 27 21:48:50 CST 2021 at org.springframework.transaction.support.ResourceHolderSupport.checkTransactionTimeout(ResourceHolderSupport.java:155) at org.springframework.transaction.support.ResourceHolderSupport.getTimeToLiveInMillis(ResourceHolderSupport.java:144) at org.springframework.transaction.support.ResourceHolderSupport.getTimeToLiveInSeconds(ResourceHolderSupport.java:128) at org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout(SpringManagedTransaction.java:125) at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:85) at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49) at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198) at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426) at com.sun.proxy.$Proxy14.insert(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:271) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:58) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59) at com.sun.proxy.$Proxy15.save(Unknown Source) at com.dashu.service.UserServiceImpl.register(UserServiceImpl.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy18.register(Unknown Source) at com.dashu.test.TestMybatisSpring.test2(TestMybatisSpring.java:35) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
5、异常属性
默认情况下抛出运行时异常的话,会回滚
public void register(User user) throws InterruptedException { // Thread.currentThread().sleep(3000); userDao.save(user); throw new RuntimeException("测试异常"); }
D:\DevelopPackage\jdk8\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar=62070:D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\bin" -Dfile.encoding=UTF-8 -classpath "D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar;D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\plugins\junit\lib\junit5-rt.jar;D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\plugins\junit\lib\junit-rt.jar;D:\DevelopPackage\jdk8\jre\lib\charsets.jar;D:\DevelopPackage\jdk8\jre\lib\deploy.jar;D:\DevelopPackage\jdk8\jre\lib\ext\access-bridge-64.jar;D:\DevelopPackage\jdk8\jre\lib\ext\cldrdata.jar;D:\DevelopPackage\jdk8\jre\lib\ext\dnsns.jar;D:\DevelopPackage\jdk8\jre\lib\ext\jaccess.jar;D:\DevelopPackage\jdk8\jre\lib\ext\jfxrt.jar;D:\DevelopPackage\jdk8\jre\lib\ext\localedata.jar;D:\DevelopPackage\jdk8\jre\lib\ext\nashorn.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunec.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunjce_provider.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunmscapi.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunpkcs11.jar;D:\DevelopPackage\jdk8\jre\lib\ext\zipfs.jar;D:\DevelopPackage\jdk8\jre\lib\javaws.jar;D:\DevelopPackage\jdk8\jre\lib\jce.jar;D:\DevelopPackage\jdk8\jre\lib\jfr.jar;D:\DevelopPackage\jdk8\jre\lib\jfxswt.jar;D:\DevelopPackage\jdk8\jre\lib\jsse.jar;D:\DevelopPackage\jdk8\jre\lib\management-agent.jar;D:\DevelopPackage\jdk8\jre\lib\plugin.jar;D:\DevelopPackage\jdk8\jre\lib\resources.jar;D:\DevelopPackage\jdk8\jre\lib\rt.jar;D:\giteesource\jdbc\spring-mybatis\target\classes;D:\DevelopPackage\repository\junit\junit\4.12\junit-4.12.jar;D:\DevelopPackage\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\DevelopPackage\repository\com\alibaba\druid\1.1.18\druid-1.1.18.jar;D:\DevelopPackage\repository\mysql\mysql-connector-java\5.1.48\mysql-connector-java-5.1.48.jar;D:\DevelopPackage\repository\org\mybatis\mybatis\3.4.6\mybatis-3.4.6.jar;D:\DevelopPackage\repository\org\springframework\spring-jdbc\5.1.14.RELEASE\spring-jdbc-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-beans\5.1.14.RELEASE\spring-beans-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-core\5.1.14.RELEASE\spring-core-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-jcl\5.1.14.RELEASE\spring-jcl-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-tx\5.1.14.RELEASE\spring-tx-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-context\5.1.4.RELEASE\spring-context-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-aop\5.1.4.RELEASE\spring-aop-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-expression\5.1.4.RELEASE\spring-expression-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\mybatis\mybatis-spring\2.0.2\mybatis-spring-2.0.2.jar;D:\DevelopPackage\repository\org\slf4j\slf4j-log4j12\1.7.25\slf4j-log4j12-1.7.25.jar;D:\DevelopPackage\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;D:\DevelopPackage\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.dashu.test.TestMybatisSpring,test2 2021-07-27 21:59:13 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@66d33a 2021-07-27 21:59:13 DEBUG XmlBeanDefinitionReader:396 - Loaded 10 bean definitions from class path resource [applicationContext.xml] 2021-07-27 21:59:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'scanner' 2021-07-27 21:59:13 DEBUG LogFactory:135 - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. 2021-07-27 21:59:13 DEBUG ClassPathMapperScanner:437 - Identified candidate component class: file [D:\giteesource\jdbc\spring-mybatis\target\classes\com\dashu\dao\UserDao.class] 2021-07-27 21:59:13 DEBUG ClassPathMapperScanner:49 - Creating MapperFactoryBean with name 'userDao' and 'com.dashu.Dao.UserDao' mapperInterface 2021-07-27 21:59:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 2021-07-27 21:59:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 2021-07-27 21:59:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionalEventListenerFactory' 2021-07-27 21:59:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 2021-07-27 21:59:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 2021-07-27 21:59:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 2021-07-27 21:59:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator' 2021-07-27 21:59:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSource' 2021-07-27 21:59:14 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 2021-07-27 21:59:14 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' 2021-07-27 21:59:14 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'sqlSessionFactoryBean' 2021-07-27 21:59:14 DEBUG SqlSessionFactoryBean:49 - Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration 2021-07-27 21:59:14 DEBUG SqlSessionFactoryBean:49 - Parsed mapper file: 'file [D:\giteesource\jdbc\spring-mybatis\target\classes\com.dashu.mapper\UserDaoMapper.xml]' 2021-07-27 21:59:14 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userService' 2021-07-27 21:59:14 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userDao' 2021-07-27 21:59:14 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSourceTransactionManager' 2021-07-27 21:59:14 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' 2021-07-27 21:59:14 DEBUG DataSourceTransactionManager:372 - Creating new transaction with name [com.dashu.service.UserServiceImpl.register]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 2021-07-27 21:59:14 INFO DruidDataSource:1003 - {dataSource-1} inited 2021-07-27 21:59:15 DEBUG DataSourceTransactionManager:265 - Acquired Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] for JDBC transaction 2021-07-27 21:59:15 DEBUG DataSourceTransactionManager:282 - Switching JDBC Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] to manual commit 2021-07-27 21:59:15 DEBUG SqlSessionUtils:49 - Creating a new SqlSession 2021-07-27 21:59:15 DEBUG SqlSessionUtils:49 - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35841320] 2021-07-27 21:59:15 DEBUG SpringManagedTransaction:49 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] will be managed by Spring 2021-07-27 21:59:15 DEBUG save:159 - ==> Preparing: Insert into tree (name,age) values (?,?) 2021-07-27 21:59:15 DEBUG save:159 - ==> Parameters: xi(String), 21(Integer) 2021-07-27 21:59:15 DEBUG save:159 - <== Updates: 1 2021-07-27 21:59:15 DEBUG SqlSessionUtils:49 - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35841320] 2021-07-27 21:59:15 DEBUG SqlSessionUtils:49 - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35841320] 2021-07-27 21:59:15 DEBUG SqlSessionUtils:49 - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35841320] 2021-07-27 21:59:15 DEBUG DataSourceTransactionManager:836 - Initiating transaction rollback 2021-07-27 21:59:15 DEBUG DataSourceTransactionManager:342 - Rolling back JDBC transaction on Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] 2021-07-27 21:59:15 DEBUG DataSourceTransactionManager:385 - Releasing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1a75e76a] after transaction java.lang.RuntimeException: 测试异常 at com.dashu.service.UserServiceImpl.register(UserServiceImpl.java:31) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy18.register(Unknown Source) at com.dashu.test.TestMybatisSpring.test2(TestMybatisSpring.java:35) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53) Process finished with exit code -1
但是如果抛出的检查异常Exception会怎么样呢?日志并没有回滚而是进行提交了,并且数据已经提交了
D:\DevelopPackage\jdk8\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar=49671:D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\bin" -Dfile.encoding=UTF-8 -classpath "D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar;D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\plugins\junit\lib\junit5-rt.jar;D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\plugins\junit\lib\junit-rt.jar;D:\DevelopPackage\jdk8\jre\lib\charsets.jar;D:\DevelopPackage\jdk8\jre\lib\deploy.jar;D:\DevelopPackage\jdk8\jre\lib\ext\access-bridge-64.jar;D:\DevelopPackage\jdk8\jre\lib\ext\cldrdata.jar;D:\DevelopPackage\jdk8\jre\lib\ext\dnsns.jar;D:\DevelopPackage\jdk8\jre\lib\ext\jaccess.jar;D:\DevelopPackage\jdk8\jre\lib\ext\jfxrt.jar;D:\DevelopPackage\jdk8\jre\lib\ext\localedata.jar;D:\DevelopPackage\jdk8\jre\lib\ext\nashorn.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunec.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunjce_provider.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunmscapi.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunpkcs11.jar;D:\DevelopPackage\jdk8\jre\lib\ext\zipfs.jar;D:\DevelopPackage\jdk8\jre\lib\javaws.jar;D:\DevelopPackage\jdk8\jre\lib\jce.jar;D:\DevelopPackage\jdk8\jre\lib\jfr.jar;D:\DevelopPackage\jdk8\jre\lib\jfxswt.jar;D:\DevelopPackage\jdk8\jre\lib\jsse.jar;D:\DevelopPackage\jdk8\jre\lib\management-agent.jar;D:\DevelopPackage\jdk8\jre\lib\plugin.jar;D:\DevelopPackage\jdk8\jre\lib\resources.jar;D:\DevelopPackage\jdk8\jre\lib\rt.jar;D:\giteesource\jdbc\spring-mybatis\target\classes;D:\DevelopPackage\repository\junit\junit\4.12\junit-4.12.jar;D:\DevelopPackage\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\DevelopPackage\repository\com\alibaba\druid\1.1.18\druid-1.1.18.jar;D:\DevelopPackage\repository\mysql\mysql-connector-java\5.1.48\mysql-connector-java-5.1.48.jar;D:\DevelopPackage\repository\org\mybatis\mybatis\3.4.6\mybatis-3.4.6.jar;D:\DevelopPackage\repository\org\springframework\spring-jdbc\5.1.14.RELEASE\spring-jdbc-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-beans\5.1.14.RELEASE\spring-beans-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-core\5.1.14.RELEASE\spring-core-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-jcl\5.1.14.RELEASE\spring-jcl-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-tx\5.1.14.RELEASE\spring-tx-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-context\5.1.4.RELEASE\spring-context-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-aop\5.1.4.RELEASE\spring-aop-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-expression\5.1.4.RELEASE\spring-expression-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\mybatis\mybatis-spring\2.0.2\mybatis-spring-2.0.2.jar;D:\DevelopPackage\repository\org\slf4j\slf4j-log4j12\1.7.25\slf4j-log4j12-1.7.25.jar;D:\DevelopPackage\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;D:\DevelopPackage\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.dashu.test.TestMybatisSpring,test2 2021-07-27 22:00:42 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4cdbe50f 2021-07-27 22:00:43 DEBUG XmlBeanDefinitionReader:396 - Loaded 10 bean definitions from class path resource [applicationContext.xml] 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'scanner' 2021-07-27 22:00:43 DEBUG LogFactory:135 - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. 2021-07-27 22:00:43 DEBUG ClassPathMapperScanner:437 - Identified candidate component class: file [D:\giteesource\jdbc\spring-mybatis\target\classes\com\dashu\dao\UserDao.class] 2021-07-27 22:00:43 DEBUG ClassPathMapperScanner:49 - Creating MapperFactoryBean with name 'userDao' and 'com.dashu.Dao.UserDao' mapperInterface 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionalEventListenerFactory' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSource' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'sqlSessionFactoryBean' 2021-07-27 22:00:43 DEBUG SqlSessionFactoryBean:49 - Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration 2021-07-27 22:00:43 DEBUG SqlSessionFactoryBean:49 - Parsed mapper file: 'file [D:\giteesource\jdbc\spring-mybatis\target\classes\com.dashu.mapper\UserDaoMapper.xml]' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userService' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userDao' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSourceTransactionManager' 2021-07-27 22:00:43 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' 2021-07-27 22:00:44 DEBUG DataSourceTransactionManager:372 - Creating new transaction with name [com.dashu.service.UserServiceImpl.register]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 2021-07-27 22:00:44 INFO DruidDataSource:1003 - {dataSource-1} inited 2021-07-27 22:00:44 DEBUG DataSourceTransactionManager:265 - Acquired Connection [com.mysql.jdbc.JDBC4Connection@33bc72d1] for JDBC transaction 2021-07-27 22:00:44 DEBUG DataSourceTransactionManager:282 - Switching JDBC Connection [com.mysql.jdbc.JDBC4Connection@33bc72d1] to manual commit 2021-07-27 22:00:44 DEBUG SqlSessionUtils:49 - Creating a new SqlSession 2021-07-27 22:00:44 DEBUG SqlSessionUtils:49 - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ae0a9ec] 2021-07-27 22:00:44 DEBUG SpringManagedTransaction:49 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@33bc72d1] will be managed by Spring 2021-07-27 22:00:44 DEBUG save:159 - ==> Preparing: Insert into tree (name,age) values (?,?) 2021-07-27 22:00:44 DEBUG save:159 - ==> Parameters: xi(String), 21(Integer) 2021-07-27 22:00:44 DEBUG save:159 - <== Updates: 1 2021-07-27 22:00:44 DEBUG SqlSessionUtils:49 - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ae0a9ec] 2021-07-27 22:00:44 DEBUG SqlSessionUtils:49 - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ae0a9ec] 2021-07-27 22:00:44 DEBUG SqlSessionUtils:49 - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ae0a9ec] 2021-07-27 22:00:44 DEBUG SqlSessionUtils:49 - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ae0a9ec] 2021-07-27 22:00:44 DEBUG DataSourceTransactionManager:743 - Initiating transaction commit 2021-07-27 22:00:44 DEBUG DataSourceTransactionManager:327 - Committing JDBC transaction on Connection [com.mysql.jdbc.JDBC4Connection@33bc72d1] 2021-07-27 22:00:44 DEBUG DataSourceTransactionManager:385 - Releasing JDBC Connection [com.mysql.jdbc.JDBC4Connection@33bc72d1] after transaction java.lang.Exception: 测试异常 at com.dashu.service.UserServiceImpl.register(UserServiceImpl.java:31) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy18.register(Unknown Source) at com.dashu.test.TestMybatisSpring.test2(TestMybatisSpring.java:35) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53) Process finished with exit code -1
@Test public void test2() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); UserService userService = (UserService) ctx.getBean("userService"); User user = new User(); user.setName("xixi"); user.setAge(21); userService.register(user); }
**总结
Spring事务处理过程中
默认 与运行时异常及其子类,采用的是回滚的策略,如果是检查异常Exception及其子类的话默认采用的事提交策略。
我们是可以改变这个策略的,需要通过异常属性来进行修改,对应的事rollbackFor = {} noRollbackFor这两个属性,一个是回滚,一个是不会滚,他们的值都是数组。实战中都采用默认
@Transactional(rollbackFor = {java.lang.Exception.class}) public void register(User user) throws Exception { // Thread.currentThread().sleep(3000); userDao.save(user); throw new Exception("测试异常"); }
@Test public void test2() throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); UserService userService = (UserService) ctx.getBean("userService"); User user = new User(); user.setName("xixixi"); user.setAge(21); userService.register(user); }
D:\DevelopPackage\jdk8\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar=51583:D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\bin" -Dfile.encoding=UTF-8 -classpath "D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\lib\idea_rt.jar;D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\plugins\junit\lib\junit5-rt.jar;D:\DevelopPackage\idea\IntelliJ IDEA 2020.2.2\plugins\junit\lib\junit-rt.jar;D:\DevelopPackage\jdk8\jre\lib\charsets.jar;D:\DevelopPackage\jdk8\jre\lib\deploy.jar;D:\DevelopPackage\jdk8\jre\lib\ext\access-bridge-64.jar;D:\DevelopPackage\jdk8\jre\lib\ext\cldrdata.jar;D:\DevelopPackage\jdk8\jre\lib\ext\dnsns.jar;D:\DevelopPackage\jdk8\jre\lib\ext\jaccess.jar;D:\DevelopPackage\jdk8\jre\lib\ext\jfxrt.jar;D:\DevelopPackage\jdk8\jre\lib\ext\localedata.jar;D:\DevelopPackage\jdk8\jre\lib\ext\nashorn.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunec.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunjce_provider.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunmscapi.jar;D:\DevelopPackage\jdk8\jre\lib\ext\sunpkcs11.jar;D:\DevelopPackage\jdk8\jre\lib\ext\zipfs.jar;D:\DevelopPackage\jdk8\jre\lib\javaws.jar;D:\DevelopPackage\jdk8\jre\lib\jce.jar;D:\DevelopPackage\jdk8\jre\lib\jfr.jar;D:\DevelopPackage\jdk8\jre\lib\jfxswt.jar;D:\DevelopPackage\jdk8\jre\lib\jsse.jar;D:\DevelopPackage\jdk8\jre\lib\management-agent.jar;D:\DevelopPackage\jdk8\jre\lib\plugin.jar;D:\DevelopPackage\jdk8\jre\lib\resources.jar;D:\DevelopPackage\jdk8\jre\lib\rt.jar;D:\giteesource\jdbc\spring-mybatis\target\classes;D:\DevelopPackage\repository\junit\junit\4.12\junit-4.12.jar;D:\DevelopPackage\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\DevelopPackage\repository\com\alibaba\druid\1.1.18\druid-1.1.18.jar;D:\DevelopPackage\repository\mysql\mysql-connector-java\5.1.48\mysql-connector-java-5.1.48.jar;D:\DevelopPackage\repository\org\mybatis\mybatis\3.4.6\mybatis-3.4.6.jar;D:\DevelopPackage\repository\org\springframework\spring-jdbc\5.1.14.RELEASE\spring-jdbc-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-beans\5.1.14.RELEASE\spring-beans-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-core\5.1.14.RELEASE\spring-core-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-jcl\5.1.14.RELEASE\spring-jcl-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-tx\5.1.14.RELEASE\spring-tx-5.1.14.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-context\5.1.4.RELEASE\spring-context-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-aop\5.1.4.RELEASE\spring-aop-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\springframework\spring-expression\5.1.4.RELEASE\spring-expression-5.1.4.RELEASE.jar;D:\DevelopPackage\repository\org\mybatis\mybatis-spring\2.0.2\mybatis-spring-2.0.2.jar;D:\DevelopPackage\repository\org\slf4j\slf4j-log4j12\1.7.25\slf4j-log4j12-1.7.25.jar;D:\DevelopPackage\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;D:\DevelopPackage\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.dashu.test.TestMybatisSpring,test2 2021-07-27 22:10:44 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@66d33a 2021-07-27 22:10:45 DEBUG XmlBeanDefinitionReader:396 - Loaded 10 bean definitions from class path resource [applicationContext.xml] 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'scanner' 2021-07-27 22:10:45 DEBUG LogFactory:135 - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. 2021-07-27 22:10:45 DEBUG ClassPathMapperScanner:437 - Identified candidate component class: file [D:\giteesource\jdbc\spring-mybatis\target\classes\com\dashu\dao\UserDao.class] 2021-07-27 22:10:45 DEBUG ClassPathMapperScanner:49 - Creating MapperFactoryBean with name 'userDao' and 'com.dashu.Dao.UserDao' mapperInterface 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionalEventListenerFactory' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSource' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'sqlSessionFactoryBean' 2021-07-27 22:10:45 DEBUG SqlSessionFactoryBean:49 - Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration 2021-07-27 22:10:45 DEBUG SqlSessionFactoryBean:49 - Parsed mapper file: 'file [D:\giteesource\jdbc\spring-mybatis\target\classes\com.dashu.mapper\UserDaoMapper.xml]' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userService' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userDao' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSourceTransactionManager' 2021-07-27 22:10:45 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' 2021-07-27 22:10:46 DEBUG DataSourceTransactionManager:372 - Creating new transaction with name [com.dashu.service.UserServiceImpl.register]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Exception 2021-07-27 22:10:46 INFO DruidDataSource:1003 - {dataSource-1} inited 2021-07-27 22:10:46 DEBUG DataSourceTransactionManager:265 - Acquired Connection [com.mysql.jdbc.JDBC4Connection@353352b6] for JDBC transaction 2021-07-27 22:10:46 DEBUG DataSourceTransactionManager:282 - Switching JDBC Connection [com.mysql.jdbc.JDBC4Connection@353352b6] to manual commit 2021-07-27 22:10:46 DEBUG SqlSessionUtils:49 - Creating a new SqlSession 2021-07-27 22:10:46 DEBUG SqlSessionUtils:49 - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@548a24a] 2021-07-27 22:10:46 DEBUG SpringManagedTransaction:49 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@353352b6] will be managed by Spring 2021-07-27 22:10:46 DEBUG save:159 - ==> Preparing: Insert into tree (name,age) values (?,?) 2021-07-27 22:10:46 DEBUG save:159 - ==> Parameters: xixixi(String), 21(Integer) 2021-07-27 22:10:46 DEBUG save:159 - <== Updates: 1 2021-07-27 22:10:46 DEBUG SqlSessionUtils:49 - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@548a24a] 2021-07-27 22:10:46 DEBUG SqlSessionUtils:49 - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@548a24a] 2021-07-27 22:10:46 DEBUG SqlSessionUtils:49 - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@548a24a] 2021-07-27 22:10:46 DEBUG DataSourceTransactionManager:836 - Initiating transaction rollback 2021-07-27 22:10:46 DEBUG DataSourceTransactionManager:342 - Rolling back JDBC transaction on Connection [com.mysql.jdbc.JDBC4Connection@353352b6] 2021-07-27 22:10:46 DEBUG DataSourceTransactionManager:385 - Releasing JDBC Connection [com.mysql.jdbc.JDBC4Connection@353352b6] after transaction java.lang.Exception: 测试异常 at com.dashu.service.UserServiceImpl.register(UserServiceImpl.java:31) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy18.register(Unknown Source) at com.dashu.test.TestMybatisSpring.test2(TestMybatisSpring.java:35) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53) Process finished with exit code -1
@Transactional(rollbackFor = {java.lang.Exception.class},noRollbackFor = {java.lang.RuntimeException.class})
事务属性常见配置总结
1、隔离属性 默认值
2、传播属性 Rqueired(默认值) 增删改 Supports查询操作
3、只读属性 readOnly false 增删改 true查询
4、超时属性 默认值-1
5、异常属性 默认值
结论:
增删改操作:@Transactional
查询操作: @Transactional(propagation=Propagation.SUPPORTS,readOnly=true)
基于标签的事务配置方式(事务开发的第二种形式)
基于注解的开发形式
<bean id="userService" class = "com.dashu.service.UserServiceImpl"> <property name="userDao" ref="userDao"/> </bean> <!--DataSourceTransactionManager--> <bean id="dataSourceTransactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> @Transactional(rollbackFor = {java.lang.Exception.class},noRollbackFor = {java.lang.RuntimeException.class}) public void register(User user) throws Exception { // Thread.currentThread().sleep(3000); userDao.save(user); throw new Exception("测试异常"); } <tx:annotation-driven transaction-manager="dataSourceTransactionManager" proxy-target-class="false"/>
基于标签的开发形式
<bean id="userService" class = "com.dashu.service.UserServiceImpl"> <property name="userDao" ref="userDao"/> </bean> <!--DataSourceTransactionManager--> <bean id="dataSourceTransactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> 事务属性+定义切入点 <tx:advice id="txAdvice" transacation-manager="dataSourceTransactionManager"> <tx:attributes> <tr:method name="register" isolation="" ,propagation=""></tx:method> <tr:method name="login" isolation="" ,propagation=""></tx:method> </tx:attributes> </tx:advice> 柱状切面 <aop:config> <aop:pointcut id = "pc" expression = "*****************"></aop:pointcut> <aop:advisor advice-ref="" pointcut-ref=""></aop:advisor> </aop:config>
基于标签的开发实战中的应用方式
<bean id="userService" class = "com.dashu.service.UserServiceImpl"> <property name="userDao" ref="userDao"/> </bean> <!--DataSourceTransactionManager--> <bean id="dataSourceTransactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> 定义切入点 <tx:advice id="txAdvice" transacation-manager="dataSourceTransactionManager"> <tx:attributes> //日后这个开头的方法都这么干,使用了*通配符 <tr:method name="modify*" isolation="" ,propagation=""></tx:method> 除了以上,剩下 ... 除了以上,剩下 ... //除了以上命名之外的所有方法 <tr:method name="*" isolation="" ,propagation=""></tx:method> </tx:attributes> </tx:advice> 简化之后的切面 <aop:config> <aop:pointcut id = "pc" expression = "优化为包切入点"></aop:pointcut> <aop:advisor advice-ref="" pointcut-ref=""></aop:advisor> </aop:config>
MVC框架整合
MVC框架整合思想
搭建Web运行环境
在Project structor当中进行创建一个maven项目,使用maven-archetype-webapp这个模式来创建maven项目(使用这种模板创建项目的好处就是好多东西都给你搭建好了。),项目下Src>main>webapps,此目录是web应用所在的位置,在main下创建源码包和资源包,这样的话,源码包、资源包、resource是平级的关系,编译时使用,所以scope是provided
<?xml version="1.0" encoding="UTF-8"?> <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.dashu</groupId> <artifactId>sring-mvc</artifactId> <version>V1.0.1</version> <packaging>war</packaging> <name>sring-mvc Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!--源码的编译版本,编译之后的版本改为1.8--> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <!--servlet,jsp,jstl相关jar包开始,这些都是web相关的jar包--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> </dependency> <!--servlet,jsp,jstl相关jar包结束--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--引入spring需要的jar包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.1.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.14.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.1.14.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.1.14.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.1.14.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.4.RELEASE</version> </dependency> <!--这个是Spring和mybatis整合的JAR包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> <!--整合log4j日志框架kaishi--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> <build> <finalName>sring-mvc</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
#resources?件夹根?录下 log4j.rootLogger=debug,console #日志输出到控制台 log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.Target=System.Out log4j.appender.console.layout=org.apache.log4j.PatternLayout #log4j.appender.console.layout.ConversionPattern=[caoshanshan] %d{yyyy-MM-dd HH:mm:ss,SSS} - %-4r %-5p [%t] %C:%L %x - %m%n log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
为什么整合MVC框架
1、MVC框架提供了控制器也就是Controller,用于调用Service对象,目前我们的JavaEE是分层开发的,有Controller层,有Service层,有Dao层,通过前面的Spring整合Dao层之后,一旦Service开发完成之后,需要有控制器来进行调用,这个控制器是由MVC框架来提供的。
2、MVC框架可以进行请求响应的处理,在web应勇开发过程中,如何处理客户提出的请求,如何为客户提出请求进行响应,这也是MVC框架的工作
3、MVC框架可以处理请求参数,底层也就是request.getParameter(“”);
4、控制器可以根绝用户的需求决定调用哪个Service,这样就可以控制着程序的运行流程,可以控制程序运行流程
5、MVC框架提供了视图解析器,这个响应使用什么类型的进行响应呢?(JSP,JSON,freemarker,Thyemeleaf(Springboot支持的))视图解析器会根据我们的设计返回jsp还是其他的东西,这也是MVC框架提供的功能。
Spring可以整合哪些MVC框架
1、struts1
2、webwork
3、jsf
4、struts2
5、springMVC
以上都可以Spring与之进行整合,SpringMVC最为重要Mvc框架,这是当前应用最为广泛的MVC框架
Spring整合MVC框架核心思路
1、准备工厂
Spring工厂是Spring框架最为核心的内容,有了工厂才能有Spring其他的属性。在我们之前的学习中,我们把工厂对象的创建永远是写在单元测试中单元测试的第一行的代码永远是创建工厂对象,作为我们来讲,我们整合MVC框架,整合MVC框架也就是要进行web开发,在web开发中我们怎么创建工厂对象呢?这是我们需要解决的第一个问题,我们创建工厂的思路是没有改变的,都是这一行代码,通过new的方式创建工厂对象,只不过整合了MVC框架之后,我们使用的工厂对象变成了另外的一个,工厂创建好了之后,我们需要解决的第二个问题是,我们如何保证工厂唯一且同时可以被公用,工厂是重量级资源,只能创建一次,需要保证他的唯一性。我们如何来解决这个问题呢?web开发过程中,我们讲过web开发过程当中的几个作用域(request,session,ServletContext(application)),这几个作用域是专门用来存储对象的,工厂创建好之后存储到了ServletContext作用域当中,也就是把工厂对象存放在ServletContext这个对象当中,就可以被大家公用了。把工厂存储在ServletContext这个作用域当中,底层实际上就是一个ServletContext.setAttribute(“xxxx”,ctx);,这样就解决了功用的问题。比共用更加重要的问题就是这个工厂怎么保证他的唯一性?也就是说我们怎么保证Spring工厂创建的代码
只被调用一次呢?刚才我们提到了ServletContext这个对象,这个对象是全局唯一的,只要我们保证工厂对象伴随着ServletContext对象的创建就可以了,创建ServletContext对象的同时创建工厂对象,这样就可以保证工厂对象也只被创建一次,因为ServletContext对象只被创建一次,所以工厂对象也就只被创建一次。ServletContext对象何时创建呢?我们通ServletContextListener对象就可以知道,这个是ServletContext对象的监听器,通过这个监听器就知道ServletContext对象是何时创建的,只要被这个监听器监听到,我们就可以执行一些功能,而且这个功能只执行一次。所以,创建工厂对象的代码是写ServletContextListener这个监听器对象当中的。因为ServletContext对象只创建一次,所以ServletContextListener对象只会被调用一次,在被调用的同时执行工厂对象的创建,这样就完美解决了工厂对象创建唯一的问题。
思路总结:
在开发创建工厂的过程当中,我们既要创建工厂,又要保证工厂对象的唯一性和供用性,我们只需要把创建工厂的代码写在监听器里边就可以保证工厂对象的唯一性,然后把这个工厂对象存储到作用域当中就解决了工厂对象公用的问题。这就是Spring工行对象以上就是Web环境下工厂对象的创建需要解决的问题,当然我们能想到Spring肯定也可以,spring已经把这些代码帮我们封装好了,Spring封装了一个ContextLoaderListener这样的一个类,封装的就是上边
工厂创建和保存的代码,所以无需我们写什么。我们将来只需要使用这各类就可以了,两个作用:创建工厂+保存工厂。因为只有是这个接口的实现类才可以监听作用域对象的创建。
//这个类实现了ServletContextListener这个类, public class ContextLoaderListener extends ContextLoader implements ServletContextListener { public ContextLoaderListener() { } public ContextLoaderListener(WebApplicationContext context) { super(context); } public void contextInitialized(ServletContextEvent event) { this.initWebApplicationContext(event.getServletContext()); } public void contextDestroyed(ServletContextEvent event) { this.closeWebApplicationContext(event.getServletContext()); ContextCleanupListener.cleanupAttributes(event.getServletContext()); } }
if (this.context == null) { this.context = this.createWebApplicationContext(servletContext); } servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ContextLoadListener使用方式,只需要在web.xml当中进行配置即可,一个是配置的监听器的创建,另一个配置的是监听器中Spring创建工厂对象的时候指定配置文件的位置。
2、代码整合
假设我们现在有一个控制器,证控制器可以是SpringMVC的Controller,也可以是Struts2的action,控制器的三个作用:1、接收客户端的请求参数,2、调用Service对象,3、返回结果流程跳转。在这里我们可以知道Controller是依赖Service的,所以我们就可以将Service作为依赖,最终通过Spring进行依赖注入,在配置文件中进行赋值。
整合的核心:依赖注入
Spring开发过程中多配置文件的处理
Spring的核心配置文件将来会越来越多,配置文件越来越长,这样不利于我们的维护,Spring为我们提供了多配置文件的开发方式就是在Spring当中提供多个核心配置文件的机制这样可以进行分门别类的区分,有利于我们的维护,Spring核心配置文件可以随意取,取多个不同的名字就好了比如:
applicationContext-dao.xml
applicationContext-service.xml
applicationContext-action.xml
分割成多个配置文件之后如何进行整合呢?
一共有两种方式
第一种方式是通配符的方式
1、非web环境下
ApplicationContext ctx = new ClassPathXmlApplicatonContext(“/applicationContext-*.xml”)
2、web环境下
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-*.xml</param-value> </context-param>
第二种是通过import标签
这种方式需要提供一个主配置文件,比如说:applicatonContext.xml在这个配置文件当中写
<import resource="applicatonContext-dao.xml"/> <import resource="applicatonContext-service.xml"/> <import resource="applicatonContext-action.xml"/>
将来在操作的时候web和非web操作这一个配置文件就可以了。