java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring事务

Spring集成事务代码实例

作者:喜上编程

这篇文章主要介绍了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事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文