spring事务实现的几种方式

2023-05-16

一、前言

1.、事务几种实现方式
(1)编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
(2)基于 TransactionProxyFactoryBean的声明式事务管理
(3)基于 @Transactional 的声明式事务管理
(4)基于Aspectj AOP配置事务

二、编程式事务管理

2.1 transactionTemplate

此种方式是自动的事务管理,无需手动开启、提交、回滚。

1.配置事务管理器

<!-- 配置事务管理器 ,封装了所有的事务操作,依赖于连接池 -->
	   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	   		<property name="dataSource" ref="dataSource"></property>
	   </bean>

2.配置事务模板对象


<!-- 配置事务模板对象 -->
       <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager"></property>
        </bean>

3.测试


@Controller
@RequestMapping("/tx")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class TransactionController {

	@Resource
	public TransactionTemplate transactionTemplate;

	@Resource
	public DataSource dataSource;

	private static JdbcTemplate jdbcTemplate;

	private static final String INSERT_SQL = "insert into cc(id) values(?)";
	private static final String COUNT_SQL = "select count(*) from cc";

	@Test
	public void TransactionTemplateTest(){
		//获取jdbc核心类对象,进而操作数据库
		jdbcTemplate = new JdbcTemplate(dataSource);
		//通过注解 获取xml中配置的 事务模板对象
		transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
		//重写execute方法实现事务管理
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				jdbcTemplate.update(INSERT_SQL, "33");   //字段sd为int型,所以插入肯定失败报异常,自动回滚,代表TransactionTemplate自动管理事务
			}
		});
		int i = jdbcTemplate.queryForInt(COUNT_SQL);
		System.out.println("表中记录总数:"+i);
	}

}

2.2 PlatformTransactionManager

使用 事务管理器 PlatformTransactionManager 对象,PlatformTransactionManager是DataSourceTransactionManager实现的接口类
此方式,可手动开启、提交、回滚事务。

1.只需要:配置事务管理


<!-- 配置事务管理 ,封装了所有的事务操作,依赖于连接池 -->
	   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	   		<property name="dataSource" ref="dataSource"></property>
	   </bean>

2.测试

@Controller
@RequestMapping("/tx")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class TransactionController {

   @Resource
	public PlatformTransactionManager transactionManager;//这里就是将配置数据管理对象注入进来,
	
	@Resource
	public DataSource dataSource;
	
	private static JdbcTemplate jdbcTemplate;

	private static final String INSERT_SQL = "insert into cc(id) values(?)";
	private static final String COUNT_SQL = "select count(*) from cc";

	@Test
	public void showTransaction(){
		//定义使用隔离级别,传播行为
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		//事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务
		TransactionStatus transaction = transactionManager.getTransaction(def);
		jdbcTemplate = new JdbcTemplate(dataSource);
		int i = jdbcTemplate.queryForInt(COUNT_SQL);
		System.out.println("表中记录总数:"+i);
		try {
			jdbcTemplate.update(INSERT_SQL,"2");
			jdbcTemplate.update(INSERT_SQL,"是否");//出现异常,因为字段为int类型,会报异常,自动回滚
			transactionManager.commit(transaction);
		}catch (Exception e){
			e.printStackTrace();
			transactionManager.rollback(transaction);
		}
		int i1 = jdbcTemplate.queryForInt(COUNT_SQL);
		System.out.println("表中记录总数:"+i1);
	}
}

三、声明式事务管理

3.1 基于Aspectj AOP开启事务

1.配置事务通知

<!-- 	   配置事务增强 -->
	   <tx:advice id="txAdvice"  transaction-manager="transactionManager">
      	<tx:attributes>
	      	<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
      	</tx:attributes>
       </tx:advice>

2.配置织入


<!--       aop代理事务。扫描 cn.sys.service 路径下所有的方法 -->
       <aop:config>
       <!--     扫描 cn.sys.service 路径下所有的方法,并加入事务处理 -->
      	<aop:pointcut id="tx"  expression="execution(* cn.sys.service.*.*(..))" />
      	<aop:advisor advice-ref="txAdvice" pointcut-ref="tx" />
      </aop:config>

3.一个完整的例子

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.2.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
           
       <!-- 创建加载外部Properties文件对象 -->
       <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
       		<property name="location" value="classpath:dataBase.properties"></property>
       </bean>
    <!-- 引入redis属性配置文件 -->
    <import resource="classpath:redis-context.xml"/>

       <!-- 配置数据库连接资源 -->
       <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" scope="singleton">
       		<property name="driverClassName" value="${driver}"></property>
       		<property name="url" value="${url}"></property>
       		<property name="username" value="${username}"></property>
       		<property name="password" value="${password}"></property>

       		<property name="maxActive" value="${maxActive}"></property>
       		<property name="maxIdle" value="${maxIdle}"></property>
       		<property name="minIdle" value="${minIdle}"></property>
       		<property name="initialSize" value="${initialSize}"></property>
       		<property name="maxWait" value="${maxWait}"></property>
       		<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}"></property>
       		<property name="removeAbandoned" value="${removeAbandoned}"></property>

       		<!-- 配置sql心跳包 -->
       		<property name= "testWhileIdle" value="true"/>
			<property name= "testOnBorrow" value="false"/>
			<property name= "testOnReturn" value="false"/>
			<property name= "validationQuery" value="select 1"/>
			<property name= "timeBetweenEvictionRunsMillis" value="60000"/>
			<property name= "numTestsPerEvictionRun" value="${maxActive}"/>
       </bean>

<!--创建SQLSessionFactory对象  -->
       <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
       		<property name="dataSource" ref="dataSource"></property>
       		<property name="configLocation" value="classpath:MyBatis_config.xml"></property>
       </bean>

       <!-- 创建MapperScannerConfigurer对象 -->
       <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
       		<property name="basePackage" value="cn.sys.dao"></property>
       </bean>

       <!-- 配置扫描器   IOC 注解 -->
	   <context:component-scan base-package="cn.sys" />

	   <!-- 配置事务管理 ,封装了所有的事务操作,依赖于连接池 -->
	   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	   		<property name="dataSource" ref="dataSource"></property>
	   </bean>

        <!-- 配置事务模板对象 -->
       <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager"></property>
        </bean>

<!-- 	  配置事务增强 -->
	   <tx:advice id="txAdvice"  transaction-manager="transactionManager">
      	<tx:attributes>
	      	<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
      	</tx:attributes>
       </tx:advice>
       
<!--     aop代理事务 -->
       <aop:config>
      	<aop:pointcut id="tx"  expression="execution(* cn.sys.service.*.*(..))" />
      	<aop:advisor advice-ref="txAdvice" pointcut-ref="tx" />
      </aop:config>
</beans>

这样就算是给 cn.sys.service下所有的方法加入了事务
也可以用springboot的配置类方式:

package com.junjie.test;

@Configurationpublic 
class TxAnoConfig {    
    /*事务拦截类型*/    
    @Bean("txSource")
    public TransactionAttributeSource transactionAttributeSource() {   
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource(); 
        /*只读事务,不做更新操作*/        
        RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, Collections.singletonList(new RollbackRuleAttribute(Exception.class)));   
        requiredTx.setTimeout(60);   
        Map<String, TransactionAttribute> txMap = new HashMap<>();   
        txMap.put("*", requiredTx);  
        source.setNameMap(txMap);    
        return source; 
    }   
    /**     * 切面拦截规则 参数会自动从容器中注入     */    
    @Bean 
    public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor) { 
        AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();  
        pointcutAdvisor.setAdvice(txInterceptor);    
        pointcutAdvisor.setExpression("execution (* com.cmb..*Controller.*(..))");   
        return pointcutAdvisor;   
    } 
    /*事务拦截器*/ 
    @Bean("txInterceptor")   
    TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx) {    
        return new TransactionInterceptor(tx, transactionAttributeSource()); 
    }
}

3.2 基于注解的 @Transactional 的声明式事务管理

@Transactional
public int saveRwHist(List list) {
return rwDao.saveRwHist(list);
}
这个注解的开启需要在spring.xml里加上一个开启注解事务的配置

四、总结

以上的开启事务方式,仅需要了解即可,如今在工作中,一般不会用到这几种方式,过于繁琐。一般都是直接用springboot自带的@Transactional 注解,就可以完成这些事务管理操作。但是如果想知道事务底层的实现原理,以上的几种原始方式,还是可以参考一下的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring事务实现的几种方式 的相关文章

  • 如何从控制器访问片段中的片段?

    我有一个名为 cutleryCustomerSearch 的视图 其中包含 替换 一个片段 div div div div 在此片段中 我有一个表 我喜欢通过 ajax 更新它 table 我如何设置处理 ajax 请求的控制器方法的返回
  • 在 Spring 中为 @Pathvariable 添加类级别验证

    在发布这个问题之前 我已经做了很多研究并尝试了很多可用的解决方案 这是我陷入的棘手情况 我有一个 Spring 控制器 它有多个请求映射 它们都有 PathVariables 控制器如下所示 Controller EnableWebMvc
  • 使用@Transactional注解批量插入

    在我的 Spring 应用程序中 我想一次性在数据库中插入近 1500 条记录 我在后端使用 Spring 4 X 和普通休眠 在我的服务层中 我使用 Transactional 注释 现在 在某个时间点之后插入记录时 我遇到内存不足错误
  • 什么是春季里程碑?

    我必须学习使用 Maven 和 Spring 在网络上 我在不同的地方看到了术语 spring里程碑 和 spring里程碑存储库 但这是一个里程碑吗 我用谷歌搜索了一下 但没有找到满足我好奇心的定义 谁能帮我 里程碑是项目管理术语 htt
  • Spring Data Rest 多对多 POST

    首先 让我解释一下我的用例 这非常简单 有一个用户实体和一个服务实体 我使用 UserService 作为连接实体 连接表 在用户和服务之间建立多对多关联最初 会有一些用户集和一些服务集 用户可以在任何时间点订阅任何服务 在这种情况下 将向
  • Websocket java 客户端 Spring + Stomp:传输错误:ConnectionLostException

    我正在尝试使用 Stomp 和 Sockjs 创建一个独立的 Java 应用程序作为今年 Spring 的 websocket 客户端 考虑到 spring 规范和 spring portafolio 示例 我收到此错误 15 18 01
  • 如何在spring mvc框架中运行后台进程

    我有一个网络应用程序 使用 spring mvc 框架 它使得以下内容 用户将文件上传到服务器 立即进入成功页面 使用该文件运行后台进程 那么 我如何使用 spring mvc 框架来做到这一点呢 先感谢您 使用异步标记方法 你在这里有例子
  • 在 Spring 上下文中查找方法级自定义注释

    我想知道的是 所有的类 方法Spring http en wikipedia org wiki Spring Framework注释为 Versioned的bean 我创建了自定义注释 Target ElementType METHOD E
  • 如何更改 Spring OAuth2 上的response_type

    这是我使用 Instagram 进行 OAuth2 登录的配置 instagram client clientId clientId clientSecret clientSeret accessTokenUri https api ins
  • Spring RESTful控制器方法改进建议

    我是 Spring REST 和 Hibernate 的新手 也就是说 我尝试组合一个企业级控制器方法 我计划将其用作未来开发的模式 您认为可以通过哪些方法来改进 我确信有很多 RequestMapping value user metho
  • 使用 Spring 和 Angular 进行 Html5 路由

    我正在尝试使用 Spring boot 和 Angular 1 5 实现 HTML5 路由 如下本文 https spring io blog 2015 05 13 modularizing the client angular js an
  • 使用 Spring 控制器处理错误 404

    I use ExceptionHandler处理我的网络应用程序抛出的异常 在我的例子中我的应用程序返回JSON回应HTTP status用于对客户端的错误响应 但是 我正在尝试弄清楚如何处理error 404返回与处理的类似的 JSON
  • 如何在 HandlerInterceptorAdapter 中添加 HttpServletRequest 标头?

    我正在尝试将授权标头添加到我的请求中 作为我们切换环境时的临时解决方法 我试图在扩展 HandlerInterceptorAdapter 的拦截器中处理它 我使用 MutableHttpServletRequest 类制作here http
  • 如何在 Spring Boot 1.4 中使用 @DataJpaTest 和 SpringFox @EnableSwagger2 进行切片测试

    Re https spring io blog 2016 04 15 testing improvements in spring boot 1 4 https spring io blog 2016 04 15 testing impro
  • Spring Security 自定义过滤器

    我想自定义 Spring security 3 0 5 并将登录 URL 更改为 login 而不是 j spring security check 我需要做的是允许登录 目录并保护 admin report html 页面 首先 我使用教
  • @RestController 没有 @ResponseBody 方法工作不正确

    我有以下控制器 RestController RequestMapping value base url public class MyController RequestMapping value child url method Req
  • Spring Data JPA 选择不同

    我有一个情况 我需要建立一个select distinct a address from Person a 其中地址是 Person 内的地址实体 类型的查询 我正在使用规范动态构建我的 where 子句并使用findAll Specifi
  • 如何从引用的java项目访问静态资源(WEB-INF)文件夹中的文件?

    我有一个 Web 应用程序 其中包含一个作为 spring bean 公开的应用程序服务之一的配置 xml 文件 另外 我在同一工作区中有一个独立的 java 应用程序 它从其 pom xml 引用我的 Web 应用程序项目 它使用 Spr
  • Grails transactionManager 运行时出现异常

    当编译一个grails v2 3 3项目运行项目时出现以下错误Netbeans 7 4 Loading Grails 2 3 3 Configuring classpath Configuring classpath Environment
  • 春季 CORS。在允许的来源中添加模式

    查看CORS的弹簧指南 以下代码启用所有允许的来源 public class MyWebMVCConfigurer extends WebMvcConfigurerAdapter Override public void addCorsMa

随机推荐

  • FixedThreadPool 使用方法测试

    public class testFixedThreadPool 固定大小的线程池 同时可以处理 参数 个任务 xff0c 多余的任务会排队 xff0c 当处理完一个马上就会去接着处理排队中的任务 Callable的任务在后面的blog有更
  • 【机器学习】西瓜书_周志华,习题集6.2,使用LIBSVM在西瓜数据集3.0a上分别用线性核和高斯核训练一个SVM,并比较其支持向量的差别。

    机器学习 西瓜书 周志华 xff0c 习题集6 2 xff0c 使用LIBSVM在西瓜数据集3 0a上分别用线性核和高斯核训练一个SVM xff0c 并比较其支持向量的差别 参考资料 xff1a LibSVM xff1a https www
  • python库pydot运行出现:FileNotFoundError:“dot.exe” not found in path

    源代码参考 此博客 xff0c 运行在win10系统下 在最后一行输出pdf文件出了如下bug graph 0 write pdf 34 iris pdf 34 解决方法 xff1a 先确认已经安装Graphviz xff0c 安装过程不赘
  • 关于char类型转换为int类型

    package HomeWork import java util Scanner public class Demo10 public static void main String args String a 61 new Scanne
  • Micapipe:一个用于多模态神经成像和连接组分析的管道

    摘要 多模态磁共振成像 xff08 MRI xff09 通过促进对大脑跨多尺度和活体大脑的微结构 几何结构 功能和连接组的分析 xff0c 加速了人类神经科学 然而 xff0c 多模态神经成像的丰富性和复杂性要求使用处理方法来整合跨模态的信
  • 电脑设置ftp共享文件的方法

    1 首先打开控制面板 xff0c 找到程序 打开或关闭Windows功能选项 2 找到internet信息服务项把其下面的所有子功能全部勾选 3 等待短时间服务配置完成后 xff0c 右键我的电脑打开管理 xff0c 选择internet信
  • C#窗体控件--button

    本文介绍C 窗体控件的 button 该控件是窗体中实现按钮点动 xff0c 触发事件则由程序逻辑进行 操作流程 1 1 添加控件 新建一个窗体 xff0c 在界面中添加Button控件如下所示 xff1a 1 2 控件属性设置 设置控件的
  • Android APK资源加载流程

    概述 我们在Activity中访问资源 xff08 图片 xff0c 字符串 xff0c 颜色等 xff09 是非常方便的 xff0c 只需要getResources 获取一个Resources对象 xff0c 然后就可以访问各种资源了 x
  • 倍福位置记忆--TwinCAT对绝对值编码器溢出圈数的处理--以汇川IS620N为例

    首先配置伺服 xff0c 如下所示 xff1a 根据伺服手册和编码器反馈的数值可知 xff0c 其每转脉冲数 xff0c 和最大的记忆圈数 xff1a 型号 xff1a IS620N 编码器位数 xff1a 8388608 最大 xff1a
  • 【LeetCode 】160. 相交链表(高频!字节面试题 双指针法 Python 7行代码 中学追及问题)

    1 题目描述 编写一个程序 xff0c 找到两个单链表相交的起始节点 如下面的两个链表 xff1a 在节点 c1 开始相交 示例 1 xff1a 输入 xff1a intersectVal span class token operator
  • Android中Paint字体的灵活使用

    在Android开发中 xff0c Paint是一个非常重要的绘图工具 xff0c 可以用于在控制台应用程序或Java GUI应用程序中绘制各种形状和图案 其中 xff0c Paint setText 方法是用于设置Paint绘制的文本内容
  • HTML5字体集合的实践经验

    随着互联网的发展 xff0c 网站已成为人们获取信息和交流的重要平台 而一个好的网站 xff0c 不仅需要有美观的界面 xff0c 还需要有良好的用户体验 其中 xff0c 字体是影响用户体验的一个重要因素 下面就让我们来看看HTML字体集
  • 20220806 美团笔试五道编程题(附AK题解)

    恭喜发现宝藏 xff01 微信搜索公众号 TechGuide 回复公司名 xff0c 解锁更多新鲜好文和互联网大厂的笔经面经 作者 64 TechGuide 全网同名 点赞再看 xff0c 养成习惯 xff0c 您动动手指对原创作者意义非凡
  • css中样式类型及属性值的获取

    前言 以前真的没怎么重视 xff0c 然后突然就遇到了与之相关的一个问题 xff0c 最后百度解决了这个问题 xff0c 因此简单记录一下 css样式类型 css样式主要分为三种类型 xff1a 1 内联样式 xff08 行内样式 xff0
  • Ubuntu 18.04版本设置root账户

    Linux系统下文件的权限十分重要 xff0c 大多数操作都需要一定的权限才可以操作 xff0c Ubuntu18 04默认安装是没有设置root账户的 xff0c 因此想要获得root账户登录可以使用以下步骤 xff1a 1 首先获得临时
  • Content-Type: application/vnd.ms-excel 操作文件

    如果要将查询结果导出到Excel xff0c 只需将页面的Context Type修改一下就可以了 xff1a header Content Type application vnd ms excel gt 如果希望能够提供那个打开 保存的
  • win7重装的坑:启动分区不存在 使用分区工具修正

    其实安装win7几个步骤 xff1a 制作启动硬盘 xff08 先制作启动盘 xff0c 再将下载好的ios镜像文件放入 xff09 使用一键安装工具安装系统修改引导启动项 原来的系统盘上面会有原来的主引导文件 xff08 MBR MSR格
  • IN和EXISTS的区别和使用

    一 结论 in 适合子表比主表数据小的情况 exists 适合子表比主表数据大的情况 当主表数据与子表数据一样大时 in与exists效率差不多 可任选一个使用 二 区别 2 1 in的性能分析 select from A where id
  • Android自定义ViewGroup交互进阶,右滑进入详情

    自定义Viewgroup右滑进入详情 前言 在之前的 ViewGroup 的事件相关一文中 xff0c 我们详细的讲解了一些常见的 ViewGroup 需要处理的事件与运动的方式 我们了解了如何处理拦截事件 xff0c 如何滚动 xff0c
  • spring事务实现的几种方式

    一 前言 1 事务几种实现方式 xff08 1 xff09 编程式事务管理对基于 POJO 的应用来说是唯一选择 我们需要在代码中调用beginTransaction commit rollback 等事务管理相关的方法 xff0c 这就是