一、什么是事物
1.说白了就是保证数据的一致性。
2.事务的特性:
2.1.原子性:要么全部成功,要么全部失败,不可再分。
2.2.一致性:例如,A用户5000元,B用户0元,转账之后B用户5000元,A用户0元,A+B总和不变为5000元。
2.3.隔离性:多个事务之间互不影响。
2.4.持久性
二、事务的分类
1.编程式事务:手动事务就是自己begin,commit。
2.声明式事务:基于xml和注解@transactional
三、环境搭建(我使用的是springboot环境)
1.项目结构
2.pom.xml
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ysfj</groupId>
<artifactId>transactiondemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>transactiondemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="userDao" class="com.ysfj.transactiondemo.dao.UserDao"></bean>
<bean id="userSerivce" class="com.ysfj.transactiondemo.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 扫描包范围 -->
<context:component-scan base-package="com.ysfj.transactiondemo"></context:component-scan>
<!-- 1. 数据源对象: C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test1"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 2. JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事物 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
4.db.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解 -->
<context:component-scan base-package="com.ysfj.transactiondemo"></context:component-scan>
<!-- 1. 数据源对象: C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test1"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 2. JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事物 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
5.UserService.java
@Service
public class UserService {
@Resource(name = "userDao02")
private UserDao userDao;
public void add() {
System.out.println(" userService02 add...");
userDao.add("chenmingxu", 18);
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
System.out.println("setUseDao");
this.userDao = userDao;
}
}
6.UserDao.java
@Repository("userDao02")
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void add(String name, Integer age) {
String sql = "INSERT INTO users(NAME, age) VALUES(?,?);";
int update = jdbcTemplate.update(sql, name, age);
System.out.println("数据库添加user成功..insert:" + update);
}
public void add() {
System.out.println("userDao002 add....");
}
}
7.SpringTest001.java
public class SpringTest001 {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("db.xml");
UserService userService = (UserService) app.getBean("userService");
userService.add();
}
}
8.建表语句
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`NAME` varchar(20) DEFAULT NULL,
`age` int(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
9.结果(成功插入数据库一条消息)
四、编程式事务(手动事物)
1.原理:获取到该数据源的api,数据源api中会自动封装手动begin,commit,rollback.
2.项目结构
3.TranscationUtils.java
@Component
public class TransactionUtils {
//拿到事务管理器
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
//开启事务
public TransactionStatus begin(){
TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
return transaction;
}
//提交事物
public void commit(TransactionStatus transaction){
dataSourceTransactionManager.commit(transaction);
}
//回滚事物
public void rollback(TransactionStatus transaction){
dataSourceTransactionManager.rollback(transaction);
}
}
4.在UserService.java中添加事物
//默认注入容器 id userService
@Service
public class UserService {
@Resource(name = "userDao02")
private UserDao userDao;
//注入事物
@Autowired
private TransactionUtils transactionUtils;
public void add() {
System.out.println(" userService02 add...");
TransactionStatus begin=null;
try {
begin = transactionUtils.begin();
userDao.add("chenmingxu", 18);
int i = 1/0;
//这样写报异常之后就不走commit()了,要回滚事物
transactionUtils.commit(begin);
}catch (Exception e){
e.printStackTrace();
//事物一旦开启要释放,不然会报错,一个提交,一个回滚
transactionUtils.rollback(begin);
}
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
System.out.println("setUseDao");
this.userDao = userDao;
}
}
5.数据库情况
五、声明事物管理(xml或者注解,AOP管理事物)
1.基于AOP的事物管理(使用声明式事物方法一定不要try,将异常抛出去),声明事物原理:AOP编程+环绕通知+异常通知
1.1.项目结构(maven,上面用springboot没有测试出来就改用maven了)
1.2.pom.xml
<?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.tydic</groupId>
<artifactId>transactiondemo1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>transactiondemo1 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>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- 引入Spring-AOP等相关Jar -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
</dependencies>
</project>
1.3.spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userDao" class="com.tydic.dao.UserDao"></bean>
<bean id="userSerivce" class="com.tydic.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 扫描包范围 -->
<context:component-scan base-package="com.tydic"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 切面类 -->
<bean id="aop" class="com.tydic.Aop2"></bean>
<!-- Aop配置 -->
<aop:config>
<!-- 定义一个切入点表达式: 拦截哪些方法 -->
<aop:pointcut expression="execution(* com.tydic.service.*.*(..))"
id="pt" />
<!-- 切面 -->
<aop:aspect ref="aop">
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pt" />
<!-- 前置通知: 在目标方法调用前执行 -->
<aop:before method="begin" pointcut-ref="pt" />
<!-- 后置通知: -->
<aop:after method="after" pointcut-ref="pt" />
<!-- 返回后通知 -->
<aop:after-returning method="afterReturning"
pointcut-ref="pt" />
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowing"
pointcut-ref="pt" />
</aop:aspect>
</aop:config>
<!-- 1. 数据源对象: C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test1"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 2. JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事物 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
1.4.TransactionUtils.java
@Component
public class TransactionUtils {
//拿到事务管理器
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
//开启事务
public TransactionStatus begin(){
TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
return transaction;
}
//提交事物
public void commit(TransactionStatus transaction){
dataSourceTransactionManager.commit(transaction);
}
//回滚事物
public void rollback(TransactionStatus transaction){
dataSourceTransactionManager.rollback(transaction);
}
}
1.5.AOP2.java
//定义切面
//注入Spring容器
public class Aop2 {
@Autowired
private TransactionUtils transactionUtils;
private TransactionStatus begin;
public void begin() {
// System.out.println("......前置通知......");
}
public void after() {
// System.out.println(".......后置通知......");
}
public void afterReturning() {
// System.out.println(".......运行通知......");
}
public void afterThrowing() {
System.out.println(".......异常通知......");
transactionUtils.rollback(begin);
}
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
begin = transactionUtils.begin();
System.out.println("我是环绕通知-前");
// 放行 实际方法
proceedingJoinPoint.proceed();
System.out.println("我是环绕通知-后");
transactionUtils.commit(begin);
}
}
1.6.UserService.java(调用的是add01()方法)
@Service
public class UserService {
@Resource(name = "userDao02")
private UserDao userDao;
//注入事物
@Autowired
private TransactionUtils transactionUtils;
public void add() {
System.out.println(" userService02 add...");
TransactionStatus begin=null;
try {
begin = transactionUtils.begin();
userDao.add("chenmingxu", 18);
//int i = 1/0;
//这样写报异常之后就不走commit()了,要回滚事物
transactionUtils.commit(begin);
}catch (Exception e){
e.printStackTrace();
//事物一旦开启要释放,不然会报错,一个提交,一个回滚
//transactionUtils.rollback(begin);
}
}
public void add01() {
System.out.println(" userService02 add...");
userDao.add("chenmingxu", 18);
int i = 1/0;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
System.out.println("setUseDao");
this.userDao = userDao;
}
}
1.7.SpringTest002.java
public class SpringTest002 {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) app.getBean("userService");
userService.add01();
}
}
1.8.数据库结果(还是一条结果),这样事物就交给了AOP去管理了
2.基于xml的事物管理(使用声明式事物方法一定不要try,将异常抛出去),声明事物原理:AOP编程+环绕通知+异常通知
2.1.项目结构
2.2.transaction-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="userDao" class="com.tydic.dao.UserDao"></bean>
<bean id="userSerivce" class="com.tydic.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 扫描包范围 -->
<context:component-scan base-package="com.tydic"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 1. 数据源对象: C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test1"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 2. JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事物 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事物管理器-->
<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<!--get*,find*不需要事物的-->
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="*" read-only="false" />
</tx:attributes>
</tx:advice>
<!-- Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务增强配置 -->
<aop:config>
<aop:pointcut expression="execution(* com.tydic.service.*.*(..))"
id="pt" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
</aop:config>
</beans>
2.3.UserService.java
@Service
public class UserService {
@Resource(name = "userDao02")
private UserDao userDao;
//注入事物
@Autowired
private TransactionUtils transactionUtils;
public void add() {
System.out.println(" userService02 add...");
TransactionStatus begin=null;
try {
begin = transactionUtils.begin();
userDao.add("chenmingxu", 18);
//int i = 1/0;
//这样写报异常之后就不走commit()了,要回滚事物
transactionUtils.commit(begin);
}catch (Exception e){
e.printStackTrace();
//事物一旦开启要释放,不然会报错,一个提交,一个回滚
//transactionUtils.rollback(begin);
}
}
public void add01() {
System.out.println(" userService02 add...");
userDao.add("chenmingxu", 18);
int i = 1/0;
}
public void add02() {
System.out.println(" userService02 add...");
userDao.add("chenmingxu", 18);
int i = 1/0;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
System.out.println("setUseDao");
this.userDao = userDao;
}
}
2.4.SpringTest003.java
public class SpringTest003 {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("transaction-spring.xml");
UserService userService = (UserService) app.getBean("userService");
userService.add02();
}
}
2.5.数据库结果
总结:这样也是可以回滚事物的,不会添加到数据中的,避免在业务逻辑层try,原理就和声明式事物AOP一样了(切记)
六、基于注解的事物管理(使用声明式事物方法一定不要try,将异常抛出去),声明事物原理:AOP编程+环绕通知+异常通知
1.项目结构图
2.transaction.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="userDao" class="com.tydic.dao.UserDao"></bean>
<bean id="userSerivce" class="com.tydic.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 扫描包范围 -->
<context:component-scan base-package="com.tydic"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 1. 数据源对象: C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test1"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 2. JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事物 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启注解-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
</beans>
3.UserService.java
package com.tydic.service;
import com.tydic.TransactionUtils;
import com.tydic.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
//默认注入容器 id userService
@Service
public class UserService {
@Resource(name = "userDao02")
private UserDao userDao;
//注入事物
@Autowired
private TransactionUtils transactionUtils;
public void add() {
System.out.println(" userService02 add...");
TransactionStatus begin=null;
try {
begin = transactionUtils.begin();
userDao.add("chenmingxu", 18);
//int i = 1/0;
//这样写报异常之后就不走commit()了,要回滚事物
transactionUtils.commit(begin);
}catch (Exception e){
e.printStackTrace();
//事物一旦开启要释放,不然会报错,一个提交,一个回滚
//transactionUtils.rollback(begin);
}
}
public void add01() {
System.out.println(" userService02 add...");
userDao.add("chenmingxu", 18);
int i = 1/0;
}
public void add02() {
System.out.println(" userService02 add...");
userDao.add("chenmingxu", 18);
int i = 1/0;
}
@Transactional//出错帮你回滚
public void add03() {
System.out.println(" userService02 add...");
userDao.add("chenmingxu", 18);
int i = 1/0;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
System.out.println("setUseDao");
this.userDao = userDao;
}
}
4.测试类
public class SpringTest004 {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("transaction.xml");
UserService userService = (UserService) app.getBean("userService");
userService.add03();
}
}
5.测试结果
七、事物的传播行为
1.什么是事物的传播行为:通俗的说就是事物传递给内部调用的方法。
2.事物传播行为种类
- PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择(都有事物,用当前两个表都会回滚)。
- PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起(log表中不会回滚)。
- PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
3.项目结构图
4.LogDao.java
@Repository
public class LogDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void addLog() {
jdbcTemplate.update("insert into log values (NULL ,'"+System.currentTimeMillis()+"');");
System.out.println("addlog添加完毕!");
}
}
5.LogService.java
@Service
public class LogService {
@Autowired
private LogDao logDao;
@Transactional(propagation = Propagation.REQUIRED)
public void addLog() {
logDao.addLog();
}
}
6.UserService.java
@Transactional(propagation=Propagation.REQUIRED)
public void add03() {
logService.addLog();
System.out.println(" userService02 add...");
userDao.add("chenmingxu", 18);
int i = 1/0;
}
7.SpringTest004.java
public class SpringTest004 {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("transaction.xml");
UserService userService = (UserService) app.getBean("userService");
userService.add03();
}
}
7.建表语句
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`NAME` varchar(20) DEFAULT NULL,
`age` int(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`log` mediumtext,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
8.根据实际的情况可以选择事物的传播性
八、总结
整理了三天,终于整理完了,有不懂的欢迎评论留言!!!