Spring集成事务代码实例

 更新时间:2023年10月18日 09:09:03   作者:喜上编程  
这篇文章主要介绍了Spring集成事务代码实例,pring事务的本质其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交,需要的朋友可以参考下

Spring事务

Spring事务的本质其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交。

有了Spring,我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作,使得我们把更多的精力放在处理业务上。

事实上Spring并不直接管理事务,而是提供了多种事务管理器。他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。

一、编程式事务

编程式事务管理我们可以通过PlatformTransactionManager实现来进行事务管理,同样的Spring也为我们提供了模板类TransactionTemplate进行事务管理,下面主要介绍模板类,我们需要在配置文件中配置。

applicationContext.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"
       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
">
<!--    开启注解-->
    <context:component-scan base-package="com.it.spring.tx"></context:component-scan>
<!--    引入工程中src下的db.properties文件-->
    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--    设置连接数据库的值  spring管理c3p0数据库连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${url}"></property>
        <property name="user" value="${user}"></property>
        <property name="driverClass" value="${driverClass}"></property>
        <property name="password" value="${password}"></property>
    </bean>
<!--    配置平台事物管理器-->
    <bean id="dataSourceTransactionManager" 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="dataSourceTransactionManager"></property>
    </bean>
</beans>

编写DAO接口

package com.it.spring.tx.dao;
/**
 * 实现转账业务
 */
public interface
AccountDAO {

    //出账
    void outMoney(String from,Double money);
    //入账
    void inMoney(String in,Double money);   
}

DAO实现类

package com.it.spring.tx.dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Repository
//JdbcDaoSupport就是为了简化我们dao类有关JdbcTemplate的注入的相关工作量。
public class AccountDAOImpl extends JdbcDaoSupport implements AccountDAO {
    @Resource
    private DataSource dataSource;
    //初始化dataSources
    @PostConstruct
    private  void init(){
        //调用JdbcDaoSupport的setDataSource方法  或者使用带参构造函数
        setDataSource(dataSource);
    }
    @Override
    public void outMoney(String from, Double money) {
        System.out.println(getJdbcTemplate());
            getJdbcTemplate().update("update account set money=money-? where id=?",money,from);
    }
    @Override
    public void inMoney(String in, Double money) {
            getJdbcTemplate().update("update account set money=money+? where id=?",money,in);
    }
}

service接口

package com.it.spring.tx.service;
/**
 * 实现转账业务
 */
public interface AccountService {
    void transfer(String from,String to,Double money);
}

service实现类

package com.it.spring.tx.service;
import com.it.spring.tx.dao.AccountDAO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
@Service
public class AccountServiceImpl implements AccountService {
    @Resource
    AccountDAO accountDAO;
    //而TransactionTemplate的编程式事务管理是使用模板方法设计模式对原始事务管理方式的封装
    @Resource
   private TransactionTemplate transactionTemplate;
//    @Override
//    public void transfer(String from, String to, Double money) {
//        accountDAO.outMoney(from,money);
        System.out.println(12/0);
//        //添加事务进行解决   使用TransactionTemplate模块
//        accountDAO.inMoney(to,money);
//    }


@Override
public void transfer(String from, String to, Double money) {
    //所以当我们借助TransactionTemplate.execute( ... )执行事务管理的时候,传入的参数有两种选择:
    //1、TransactionCallback
    //2、TransactionCallbackWithoutResult
    //两种区别从命名看就相当明显了,一个是有返回值,一个是无返回值。这个的选择就取决于你是读

//    //设置事务传播属性
//    transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//    // 设置事务的隔离级别,设置为读已提交(默认是ISOLATION_DEFAULT:使用的是底层数据库的默认的隔离级别)
//    transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
//    // 设置是否只读,默认是false
//    transactionTemplate.setReadOnly(true);
//    // 默认使用的是数据库底层的默认的事务的超时时间
//    transactionTemplate.setTimeout(30000);
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                    try {
                        accountDAO.outMoney(from, money);
                        System.out.println(12 / 0);
                        accountDAO.inMoney(to, money);
                    } catch (Exception e){
                        //回滚状态
                        transactionStatus.setRollbackOnly();
                    }
                }
            });
    }
}

测试类

package com.it.spring.tx.test;

import com.it.spring.tx.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration("classpath:applicationContext.xml")
public class SpringTxTest1 {
     @Resource
     AccountService accountService;
     @Test
     public void Test1(){
         accountService.transfer("18","17",1000.0);
     }
}

二、声明式事务

声明式事务管理有两种常用的方式,一种是基于tx和aop命名空间的xml配置文件,一种是基于@Transactional注解,随着Spring和Java的版本越来越高,大家越趋向于使用注解的方式,下面我们两个都说。

1.基于tx和aop命名空间的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"
       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/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <context:component-scan base-package="com.it.spring.tx2.*"></context:component-scan>
    
    <!-- 引入工程中src下的db.properties文件2-->

 <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
     <!-- spring管理c3p0数据库连接池-->

  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      <property name="driverClass" value="${driverClass}"></property>
      <property name="jdbcUrl" value="${url}"></property>
      <property name="password" value="${password}"></property>
      <property name="user" value="${user}"></property>
  </bean>
    <!--配置平台事物管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
<!--    配置增强(就是自定义的的切面) -->

<!--     配置事物增强-->

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--         propagation事务传播行为    isolation隔离机制-->
        <tx:attributes>
<!--            <tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"></tx:method>-->
<!--            <tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT"></tx:method>-->
<!--            <tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT"></tx:method>-->
<!--            <tx:method name="query*" read-only="true"></tx:method>-->
            <tx:method name="*" propagation="REQUIRED"></tx:method>
        </tx:attributes>
    </tx:advice>

<!--          配置AOP-->
    <aop:config>
<!--        设置切点-->
        <aop:pointcut id="pointcut1" expression="execution(* com.com.it.spring.tx2.service.AccountServiceImpl.transfer(..))"></aop:pointcut>
<!--        aop:aspect 多个通知和多个切入点的组合-->
        <!--aop:advisor 单个通知和单个切入点的组合-->
        <aop:advisor pointcut-ref="pointcut1" advice-ref="txAdvice"></aop:advisor>
    </aop:config>
</beans>

service实现类发生变化

package com.it.spring.tx2.service;
import com.it.spring.tx2.dao.AccountDAO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
 @Service("accountService")
public class AccountServiceImpl implements AccountService {
     @Resource
     AccountDAO accountDAO;
    @Override
    public void transfer(String from, String to, Double money) {
        accountDAO.outMoney(from,money);
//        System.out.println(12/0);
        accountDAO.inMoney(to,money);
    }
}

测试类

package com.it.spring.tx2.test;
import com.it.spring.tx2.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration("classpath:applicationContext2.xml")
public class SpringTxTest2 {
  @Resource
  AccountService accountService;
  @Test
  public void fun1(){
    accountService.transfer("11","10",1000.0);
  }
}

2.基于@Transactional注解

这种方式最简单,也是最为常用的,只需要在配置文件中开启对注解事务管理的支持。

applicationContext3.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"
       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/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">   
   <context:component-scan base-package="com.it.spring.tx3.*"></context:component-scan>   
    <!-- 引入工程中src下的db.properties文件2-->
 <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
     <!-- spring管理c3p0数据库连接池-->
  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      <property name="driverClass" value="${driverClass}"></property>
      <property name="jdbcUrl" value="${url}"></property>
      <property name="password" value="${password}"></property>
      <property name="user" value="${user}"></property>
  </bean>
    <!--配置平台事物管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
  <!-- 开启事物注解-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

services实现类

package com.it.spring.tx3.service;

import com.it.spring.tx3.dao.AccountDAO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
//在业务层添加注解
 @Service
 @Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED)
public class AccountServiceImpl implements AccountService {
     @Resource
     AccountDAO accountDAO;
    @Override
    public void transfer(String from, String to, Double money) {
        accountDAO.outMoney(from,money);
//       System.out.println(12/0);
        accountDAO.inMoney(to,money);
    }
}

以上就是Spring管理事务的方式。感谢阅读。

到此这篇关于Spring集成事务代码实例的文章就介绍到这了,更多相关Spring事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Android 单例模式 Singleton 简单实例设计模式解析

    Android 单例模式 Singleton 简单实例设计模式解析

    这篇文章主要介绍了单例模式 Singleton 简单实例设计模式解析的相关资料,需要的朋友可以参考下
    2016-12-12
  • MyBatis 动态拼接Sql字符串的问题

    MyBatis 动态拼接Sql字符串的问题

    MyBatis的动态SQL,解决了SQL字符串拼接的痛苦。下文分步骤给大家详细介绍了MyBatis 动态拼接Sql字符串的问题,非常不错,感兴趣的朋友一起看下吧
    2016-08-08
  • Netty网络编程零基础入门

    Netty网络编程零基础入门

    Netty是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端,如果你还不了解它的使用,就赶快继续往下看吧
    2022-08-08
  • SpringBoot详解整合Redis缓存方法

    SpringBoot详解整合Redis缓存方法

    本文主要介绍了SpringBoot整合Redis缓存的实现方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • Java实现简单的飞机大战游戏(控制主飞机篇)

    Java实现简单的飞机大战游戏(控制主飞机篇)

    这篇文章主要为大家详细介绍了Java实现简单的飞机大战游戏,控制主飞机,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • Java异常分类及统一处理详解

    Java异常分类及统一处理详解

    这篇文章主要为大家详细介绍了Java异常分类及统一处理,SpringMVC处理异常支持ajax,web.xml配置异常,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • Spring如何自定义加载配置文件(分层次加载)

    Spring如何自定义加载配置文件(分层次加载)

    这篇文章主要介绍了Spring如何自定义加载配置文件(分层次加载)问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • MyBatis拦截器原理探究

    MyBatis拦截器原理探究

    MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.这篇文章主要介绍了MyBatis拦截器原理探究,需要的朋友可以参考下
    2018-02-02
  • Java实现Word/Excel/TXT转PDF的方法

    Java实现Word/Excel/TXT转PDF的方法

    这篇文章主要介绍了Java实现Word/Excel/TXT转PDF的方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-01-01
  • Java Stream流零基础教程

    Java Stream流零基础教程

    Java8的另一大亮点Stream,它与java.io包里的InputStream和OutputStream是完全不同的概念,下面这篇文章主要给大家介绍了关于Java8中Stream详细使用方法的相关资料,需要的朋友可以参考下
    2022-11-11

最新评论