Java Spring 声明式事务详解

目录
  • 项目结构:
  • 表结构:
  • 基于xml的声明式事务配置
  • 完全注解(零xml)方式配置
  • 事务参数
    • no-rollback-for
    • rollback-for
    • read-only
    • timeout
    • isolation
    • propagation
  • 总结

项目结构:

表结构:

基于xml的声明式事务配置

IAccountDao.java:

package tx.dao;
import java.math.BigDecimal;
public interface IAccountDao {
    void add(String name, BigDecimal money);
    void sub(String name, BigDecimal money);
}

AccountDaoImpl.java:

package tx.service.impl;
import tx.dao.IAccountDao;
import tx.service.IAccountService;
import java.math.BigDecimal;
public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao;
    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }
    @Override
    public void tran(String from, String to, BigDecimal money) {
        accountDao.sub(from, money);
        accountDao.add(to, money);
    }
}

IAccountService.java:

package tx.service;
import java.math.BigDecimal;
public interface IAccountService {
    void tran(String from, String to, BigDecimal money);
}

AccountDaoImpl.java:

package tx.dao.impl;
import org.springframework.jdbc.core.JdbcTemplate;
import tx.dao.IAccountDao;
import java.math.BigDecimal;
public class AccountDaoImpl implements IAccountDao {
    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    @Override
    public void add(String name, BigDecimal money) {
        jdbcTemplate.update("update account set balance = balance + ? where name = ? ", money.toString(), name);
    }
    @Override
    public void sub(String name, BigDecimal money) {
        jdbcTemplate.update("update account set balance = balance - ? where name = ? ", money.toString(), name);
    }
}
<?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: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/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
       ">
    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="19834044876"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
    <!--创建事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置jdbcTemplate对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--将JdbcTemplate注入到AccountDao中-->
    <bean id="accountDao" class="tx.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
    <!--将AccountDao注入到AccountService中-->
    <bean id="accountService" class="tx.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>
    <!--配置事务通知-->
    <tx:advice id="txAdvice">
        <!--配置事务参数-->
        <tx:attributes>
            <!--指定哪些方法上面添加事务-->
            <tx:method name="tran"/>  <!-- name="*", name="tran*", name="*tran", ... -->
        </tx:attributes>
    </tx:advice>
    <!--配置切入点和切面-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pointCut" expression="execution(* tx.service.IAccountService.*(..))"/>
        <!--配置通知-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
    </aop:config>
</beans>
ApplicationContext context = new ClassPathXmlApplicationContext("tx.xml");
IAccountService accountService = context.getBean("accountService", IAccountService.class);
accountService.tran("小明", "小红", new BigDecimal(500));

完全注解(零xml)方式配置

IAccountDao.java:

package tx.dao;
import java.math.BigDecimal;
public interface IAccountDao {
    void add(String name, BigDecimal money);
    void sub(String name, BigDecimal money);
}

AccountDaoImpl.java:

package tx.dao.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import tx.dao.IAccountDao;
import java.math.BigDecimal;
@Repository
public class AccountDaoImpl implements IAccountDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public void add(String name, BigDecimal money) {
        jdbcTemplate.update("update account set balance = balance + ? where name = ? ", money.toString(), name);
    }
    @Override
    public void sub(String name, BigDecimal money) {
        jdbcTemplate.update("update account set balance = balance - ? where name = ? ", money.toString(), name);
    }
}

IAccountService.java:

package tx.service;
import java.math.BigDecimal;
public interface IAccountService {
    void tran(String from, String to, BigDecimal money);
}

AccountServiceImpl.java:

package tx.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tx.dao.IAccountDao;
import tx.service.IAccountService;
import java.math.BigDecimal;
@Service
@Transactional
public class AccountServiceImpl implements IAccountService {
    @Autowired
    private IAccountDao accountDao;
    @Override
    public void tran(String from, String to, BigDecimal money) {
        accountDao.sub(from, money);
        accountDao.add(to, money);
    }
}

TXConfig.java

package tx.config;
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;
import tx.service.IAccountService;
import tx.service.impl.AccountServiceImpl;
import javax.sql.DataSource;
@Configuration
@ComponentScan(basePackages = "tx")
@EnableTransactionManagement
public class TXConfig {
    /**
     * 配置数据源
     */
    @Bean
    public DataSource getDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/test?useSSL=false");
        dataSource.setUsername("root");
        dataSource.setPassword("19834044876");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        return dataSource;
    }
    /**
     * 创建事务管理器
     */
    @Bean
    public DataSourceTransactionManager getTransactionManager() {
        return new DataSourceTransactionManager(getDataSource());
    }
    /**
     * 配置jdbcTemplate对象
     */
    @Bean
    public JdbcTemplate getJdbcTemplate() {
        return new JdbcTemplate(getDataSource());
    }
    @Bean(name = "accountService")
    public IAccountService getAccountService() {
        return new AccountServiceImpl();
    }
}
ApplicationContext context = new AnnotationConfigApplicationContext(TXConfig.class);
IAccountService accountService = context.getBean("accountService", IAccountService.class);
accountService.tran("小明", "小红", new BigDecimal(500));

事务参数

no-rollback-for

指定碰到哪些异常不需要回滚

rollback-for

指定碰到哪些异常需要回滚

read-only

设置事务为只读事务

timeout

以秒为单位,设置事务超出指定时常后自动回滚

默认为-1,即不管事务运行多久都不回滚

isolation

事务的隔离级别

默认为DEFAULT,即使用当前数据库的隔离级别

propagation

事务的传播行为

默认为REQUIRED

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • 关于Spring中声明式事务的使用详解

    目录 一.前言 二.回顾JDBC的数据库事务 三.数据库事务隔离级别 3.1 数据库事务的基本特征 3.2 详解数据库隔离级别 3.2.1 未提交读 3.2.2 读提交 3.2.3 可重复读 3.2.4 串行化 3.2.5 各个隔离级别的总结 四.数据库事务传播行为 五.Spring中的声明式事务的使用 5.1 @Transactional的配置属性 5.2 Spring的事务管理器 5.3 配置事务的传播行为和隔离级别 六.总结 一.前言 在Spring中,数据库事务是通过AOP技术来提供服务

  • Spring注解 TX声明式事务实现过程解析

    环境搭建导入 maven依赖 <!--spring提供的数据库操作工具--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!--c3p0 数据库连接池--> &

  • spring是如何实现声明式事务的

    前言 今天我们来讲讲spring的声明式事务. 开始 说到声明式事务,我们现在回顾一下事务这个概念,什么是事务呢,事务指的是逻辑上的⼀组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功.从而确保了数据的准确与安全.事务有着四大特性(ACID),分别是 原子性(Atomicity)原⼦性是指事务是⼀个不可分割的⼯作单位,事务中的操作要么都发⽣,要么都不发⽣. ⼀致性(Consistency)事务必须使数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态. 隔离性(Isolation)事务的隔离

  • SpringBoot声明式事务的简单运用说明

    关于事物的基本概念等这里就不介绍了. Spring声明式事物的实现,有两种方式:第一种是配置xml,第二种是使用相关注解(这两种方式可详见<程序员成长笔记(一)>的相关章节).SpringBoot中默认配置了第二种方式,所以,SpringBoot直接使用注解即可.下面介绍SpringBoot通过注解开启事物的使用. SpringBoot使用事物的步骤: 第一步:在启动类上开启事物支持 提示: @EnableTransactionManagement注解其实在大多数情况下,不是必须的,因为Spr

  • Spring声明式事务注解之@EnableTransactionManagement解析

    Spring声明式事务注解之@EnableTransactionManagement 1. 说明 @EnableTransactionManagement声明在主配置类上,表示开启声明式事务,其原理是通过@Import导入TransactionManagementConfigurationSelector组件,然后又通过TransactionManagementConfigurationSelector导入组件AutoProxyRegistrar和ProxyTransactionManageme

  • Spring实现声明式事务的方法详解

    1.回顾事务 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎! 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性. 事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用. 事务四个属性ACID 原子性(atomicity) 事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用. 一致性(consistency) 一旦所有事务动作完成,事务就要被提交.数据和资源处于一种满足业务规则的一致性状态中.

  • Spring如何基于xml实现声明式事务控制

    一.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

  • Java Spring 声明式事务详解

    目录 项目结构: 表结构: 基于xml的声明式事务配置 完全注解(零xml)方式配置 事务参数 no-rollback-for rollback-for read-only timeout isolation propagation 总结 项目结构: 表结构: 基于xml的声明式事务配置 IAccountDao.java: package tx.dao; import java.math.BigDecimal; public interface IAccountDao { void add(St

  • Spring声明式事务配置使用详解

    目录 序章 准备工作 创建jdbc.properties 配置Spring的配置文件 声明式事务概念 代码讲解 配置 Spring 的配置文件 创建表 创建组件 测试无事务情况 加入事务 序章 Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作 准备工作 <dependencies> <!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 --> <dependency> <

  • Spring的编程式事务和声明式事务详解

    入口(了解一些基本概念) Spring事务属性(事务的属性有哪些?) 我们都知道事务有开始,保存点,提交,回滚,隔离级别等属性.那么Spring对于事务属性定义有哪些呢?通过TransactionDefinition接口我们可以了解到: public interface TransactionDefinition{ int getIsolationLevel(); int getPropagationBehavior(); int getTimeout(); boolean isReadOnly

  • spring声明式事务解析

    一.spring声明式事务 1.1 spring的事务管理器 spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现.spring容器负责事物的操作,spring容器充当切面,事务的方法称为增强处理,生成的代理对象的方法就是目标方法+增强也就是crud+事务程序员只用做crud的操作,也就是目标方法和声明哪些方法应该在事务中运行. Spring提供了许多内置事务管理器实现: DataSourceTransactionManager:位于or

  • spring声明式事务 @Transactional 不回滚的多种情况以及解决方案

    目录 一. spring 事务原理 问题一.@Transactional 应该加到什么地方,如果加到Controller会回滚吗? 问题二. @Transactional 注解中用不用加rollbackFor = Exception.class 这个属性值 问题三:事务调用嵌套问题具体结果如下代码: 四.总结 五. 参考链接 本文是基于springboot完成测试测试代码地址如下: https://github.com/Dr-Water/springboot-action/tree/master

  • spring声明式事务@Transactional底层工作原理

    目录 引言 工作机制简述 事务AOP核心类释义 @Transactional TransactionAttribute SpringTransactionAnnotationParser AnnotationTransactionAttributeSource TransactionAttributeSourcePointcut TransactionInterceptor BeanFactoryTransactionAttributeSourceAdvisor ProxyTransaction

  • 完美解决Spring声明式事务不回滚的问题

    疑问,确实像往常一样在service上添加了注解 @Transactional,为什么查询数据库时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚.于是就对相关代码进行了一番测试,结果发现一下踩进了两个坑,确实是事务未回滚导致的数据不一致. 下面总结一下经验教训: Spring事务的管理操作方法 编程式的事务管理 实际应用中很少使用 通过使用TransactionTemplate 手动管理事务 声明式的事务管理 开发中推荐使用(代码侵入最少) Spring的声明式事

  • spring 声明式事务实现过程解析

    这篇文章主要介绍了spring 声明式事务实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 /** * 声明式事务: * * 环境搭建: * 1.导入相关依赖 * 数数据 * 3.给方法上标注 @Transactional 表示当前方法是一个事务方法: * 4. @EnableTransactionManagement 开启基于注解的事务管理功能:据源.数据库驱动.Spring-jdbc模块 * * 2.配置数据源.JdbcTempl

  • Java Spring拦截器案例详解

    springmvc提供了拦截器,类似于过滤器,他将在我们的请求具体出来之前先做检查,有权决定接下来是否继续,对我们的请求进行加工. 拦截器,可以设计多个. 通过实现handlerunterceptor,这是个接口 定义了非常重要的三个方法: 后置处理 前置处理 完成处理 案例一: 通过拦截器实现方法耗时统计与警告 package com.xy.interceptors; import org.springframework.web.servlet.HandlerInterceptor; impo

随机推荐