目录

编程式事务

使用TransactionTamplate

使用TransactionManager

声明式事务

XML文件配置

java代码配置---@transactional


编程式事务

通过TransactionTemplate或TransactionManager手动管理事务,因为是手动,所以实际开发中很少使用。但便于理解Spring事务管理原理,建议新手先学习编程式事务。

我们通过一个案例去理解Spring中的事务,在数据表account中有zhangsan和lisi两个人,现在用编程式事务的方式实现转账功能。

首先在pom.xml文件中添加依赖spring-context + spring-jdbc + druid + mysql-connector-java + junit(用于测试)

<?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>org.example</groupId><artifactId>tx</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.18</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.18</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.9</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.27</version></dependency></dependencies>
</project>
package com.qfedu.demo.dao;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;/*** 操作类*/
@Repository
public class AccountDao {@AutowiredJdbcTemplate jdbcTemplate;/*** 向指定用户的余额中添加指定额度* @param username 指定用户* @param money 添加多少金额*/public void addMoney(String username, Double money) {jdbcTemplate.update("update account set money=money+? where username=?;", money, username);}/*** 向指定用户夫人余额减少额度* @param username 指定用户* @param money 较少多少金额*/public void minusMoney(String username, Double money) {jdbcTemplate.update("update account set money=money-? where username=?;", money, username);}
}

使用TransactionTamplate

package com.qfedu.demo.service;import com.qfedu.demo.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;/*** 服务类*/
@Service
public class AccountService {@Autowiredprotected AccountDao accountDao;@Autowiredprivate TransactionTemplate transactionTemplate;/*** 转账方法* @param from 金额减少的用户* @param to 金额增加的用户* @param money 转账的金额*/public void transferMoney(String from, String to, Double money) {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus status) {try {accountDao.minusMoney(from, money);accountDao.addMoney(to, money);} catch (Exception e) {e.printStackTrace();//回滚status.setRollbackOnly();}}});}
}

使用TransactionManager

TransactionManager是一个接口,并且是空接口。所以在具体的代码中,要用其的子类PlatformTransactionManager,在这个子类有且仅有三个方法,对应的功能分别是开启事务、提交事务和回滚事务。虽然在AccountService中使用的是PlatformTransactionManager,但是在applicationContext.xml配置文件中使用的是DataSourceTransactionManager。这利用的是泛型的知识。

package com.qfedu.demo.service;import com.qfedu.demo.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;@Service
public class AccountService01 {@Autowiredprivate AccountDao accountDao;@Autowiredprivate PlatformTransactionManager platformTransactionManager;public void TransferMoney(String from, String to, Double money) {DefaultTransactionDefinition definition = new DefaultTransactionDefinition();//开启事务TransactionStatus status = platformTransactionManager.getTransaction(definition);try {accountDao.minusMoney(from, money);accountDao.addMoney(to, money);platformTransactionManager.commit(status);} catch (Exception e) {e.printStackTrace();platformTransactionManager.rollback(status);}}
}

applicationContext.xml配置文件,如果是使用TransactionManager,可以不用配置TransactionTemplate。

<?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 https://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.qfedu.demo"/><context:property-placeholder location="classpath:db.properties"/><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="username" value="root"/><property name="password" value="123456"/><property name="url" value="jdbc:mysql:///jdbc01"/></bean><bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><!--    创建一个,MySQL数据库的事务管理器--><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"><property name="dataSource" ref="dataSource"/></bean><bean class="org.springframework.transaction.support.TransactionTemplate" id="transactionTemplate"><property name="transactionManager" ref="transactionManager"/></bean></beans>
package com.qfedu.demo.service;import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** 测试类*/
public class AccountTest01 {private ClassPathXmlApplicationContext ctx;@Beforepublic void before() {ctx = new ClassPathXmlApplicationContext("applicationContext.xml");}/*** 使用TransactionTemplate*/@Testpublic void testTransactionManager() {AccountService accountService = ctx.getBean(AccountService.class);accountService.transferMoney("zhangsan", "lisi", 50.0);}/*** 使用TransactionManager*/@Testpublic void testTransactionTemplate() {AccountService01 accountService01 = ctx.getBean(AccountService01.class);accountService01.TransferMoney("zhangsan","lisi",50.0);}
}

其实不管是使用TransactionManager,还是使用TransactionTemplate,都差不多。在实际开发中,主要是使用声明式事务, 因为声明式事务代码入侵少,其本质式通过AOP实现。

声明式事务

XML文件配置

首先在pom.xml配置文件中添加依赖,除了编程式事务的依赖外,因为使用了AOP,所以还需要aspectjrt 和 aspectjweaver

<?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>org.example</groupId><artifactId>tx02</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.18</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.18</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.9</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.27</version></dependency></dependencies>
</project>

操作类AccountDao与编程式事务的AccoutDao一样,这里不再赘叙。

相比于编程式事务,声明式事务的AccountService显得极为简介,写上自己的业务就可以了,这是由于使用了AOP,那些相同的代码提前做好了。

package com.qfedu.demo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class AccountService {@Autowiredprivate AccountDao accountDao;public void transferMoney(String from, String to, Double money) {accountDao.minusMoney(from, money);accountDao.addMoney(to, money);}
}

声明式的 applicationContext.xml 配置文件主要分为五个步骤:配置数据源、配置JdbcTemplate、配置事务管理器、配置事务属性和配置AOP。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><context:component-scan base-package="com.qfedu.demo"/><!--配置数据源--><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="url" value="jdbc:mysql:///jdbc01"/><property name="username" value="root"/><property name="password" value="123456"/></bean><!--配置jdbcTemplate--><bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><!--配置事务管理器--><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"><property name="dataSource" ref="dataSource"/></bean></beans>
package com.qfedu.demo;import org.springframework.context.support.ClassPathXmlApplicationContext;/*** 测试类*/
class AccountServiceTest01 {public static void main(String[] args) {ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");AccountService accountService = ctx.getBean(AccountService.class);accountService.transferMoney("zhangsan", "lisi", 50.0);}
}

因为声明式事务的简洁,所以在实际开发中,一般都是使用声明式事务。

java代码配置---@transactional

配置类

package com.qfedu.demo01;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;/*** 配置类*/
@Configuration
@ComponentScan
//开启事务注解,通过注解标记事务
@EnableTransactionManagement
public class JavaConfig {@BeanDruidDataSource dataSource() {DruidDataSource ds = new DruidDataSource();ds.setUrl("jdbc:mysql:///jdbc01");ds.setUsername("root");ds.setPassword("123456");return ds;}@BeanJdbcTemplate jdbcTemplate() {JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource());return jdbcTemplate;}@BeanDataSourceTransactionManager transactionManager() {DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();transactionManager.setDataSource(dataSource());return transactionManager;}}

其实就是把applicationContext.xml配置文件翻译程java代码,但是配置事务属性 和 配置AOP需要注意,applicationContext.xml中的配置事务属性对应Java代码配置@EnableTransactionManager,表示开始事务注解,之后再AccountService#transferMoney添加注解@transactioal,表示为方法添加事务。

package com.qfedu.demo01;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;/*** 服务类*/
@Service
public class AccountService {@Autowiredprivate AccountDao accountDao;//表示给方法添加事务,该注解如果在类上,则表示为该类的所有方法添加事务@Transactionalpublic void transferMoney(String from, String to, Double money) {accountDao.minusMoney(from, money);accountDao.addMoney(to, money);}
}
package com.qfedu.demo01;import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** 测试类*/
class JavaConfigTest01 {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);AccountService accountService = ctx.getBean(AccountService.class);accountService.transferMoney("zhangsan", "lisi", 50.0);}
}

总结:建议使用声明式事务,用XML配置还是Java代码配置就得看个人喜欢了。其实本人还是喜欢用XMl配置的。

Spring中的编程式事务与声明式事务相关推荐

  1. spring中编程式事务与声明式事务

    spring中使用事务有两种方式,一种是编程式,一种是声明式. 编程式事务 编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManage ...

  2. Spring事务处理之 编程式事务 和 声明式事务

    对事务概念还不了解的可以先看一下 MySQL事务管理(初步了解) 这篇文章 !!! Spring事务管理学习步骤: 1.掌握Spring事务属性 2.掌握Spring事务核心API 3.掌握Sprin ...

  3. 事务声明声明式事务和编程式事务区别

    事务声明声明式事务和编程式事务区别 1.编程式事务: 所谓编程式事务指的是通过编码方式实现事务,即类似于JDBC编程实现事务管理.管理使用TransactionTemplate或者直接使用底层的Pla ...

  4. Spring框架(下)JdbcTemplate、声明式事务管理

    Spring框架(下)JdbcTemplate.声明式事务管理 (一)使用JdbcTemplate 1.概述 为了使JDBC更加易于使用,Spring在JDBC API上定义了一个抽象层,以此建立一个 ...

  5. spring 的4种事务管理(1种编程式+3种声明式)

    见:http://blog.csdn.net/sinat_25926481/article/details/48208619 Spring的4种事务管理(1种编程式事务+三种声明事务) 一.Sprin ...

  6. 编程式事务与声明式事务

    编程式事务 1.加入jar包 com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar co ...

  7. 编程式事务与声明式事务的区别

    通俗点讲就是: 编程式事务就是自己写Try catch语句调用commit\rollback等函数来实现那段业务数据改变的事务性. 声明式事务:是通过框架和事务定义配置给自己的业务代码添加事务性,比如 ...

  8. Spring事务管理--声明式事务管理

    Spring的事务管理分为两种方式:1,传统的编程式事务管理(编码式事务管理):2,声明式事务管理. Spring的声明式事务管理是指将事务管理代码从业务方法中分离出来,以申明的方式实现事务管理.Sp ...

  9. Spring Framework--Data Access(1)--Transaction Management(2) - 声明式事务管理

    一.概述 Spring的声明式事务管理是通过Spring的AOP实现的,Spring的事务管理和EJB CMT类似,都可以在方法级别上定义事务行为,不过他们两者也有区别,表现在: (1)EJB CMT ...

最新文章

  1. 传清华应届生获Facebook offer
  2. 【7】青龙面板系列教程之任务消息定时推送
  3. 用Android Studio调试Framework层代码
  4. 官网3.15课程一起来“打价”,找群内管理员还可以折上折
  5. spring aop示例_Spring JpaRepository示例(内存中)
  6. js实现手机端、pc端相应的跳转
  7. 《HTML5 开发实例大全》——1.9 使用 summary 标记元素实现交互
  8. python创建虚拟环境报错typeerror_python 创建虚拟环境时报错OSError, setuptools下载失败...
  9. NGINX访问日志和错误日志
  10. 有关Ajax实现的两种方法
  11. 下载MySQL安装包
  12. Java后台调用第三方支付接口(易宝支付)
  13. 计算机常见知识大全,电脑基本知识
  14. GPX文件格式适用于GPS定位的模拟以及生成文件
  15. SCTP协议与程序设计案例
  16. Day77_Flink(三)Flink时间语义和水印
  17. Python入门学习二:列表
  18. 终于搞清前端和后端的区别啦!原来是这样的
  19. 黄金思维圈,看透问题本质的利器,成功者必备工具
  20. Kotlin拿Android本地视频缩略图

热门文章

  1. 【千律】C++基础:编写实现自定义的字符串拼接函数
  2. 得力Deli M351R 一体机驱动
  3. 模型测试时显存爆炸解决
  4. java kill 详解_Kill命令在Java里面详解
  5. 详细实现ESP8266WIFI时钟(基于51单片机)
  6. Linux深入理解文件系统
  7. Linux函数返回值判断if,bash函数内判断命令执行结果并返回
  8. 有没有python搜题_免费搜题公众号python
  9. App Tech Support
  10. 双卡双待手机[海信]挂断来电和指定卡去电实现