首页 > 其他分享 >Transaction事务

Transaction事务

时间:2024-06-22 22:10:54浏览次数:23  
标签:xml 事务 Transaction int bookDao public jdbcTemplate id

  • Spring Transaction 示例

1 Transaction sample

1.1 配置文件

<?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.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.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">

    <!-- 用来替换${jdbc.username} 的值 -->
    <context:property-placeholder location="classpath:dbconfig.properties"></context:property-placeholder>


    <!-- 创建数据源对象 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    </bean>

    <!-- 引入jdbctemplate 对象,用来进行db操作 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>

    <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 业务逻辑处理类  -->
    <bean id="bookService" class="com.gientech.tx.xml.service.BookService">
        <property name="bookDao" ref="bookDao"></property>
    </bean>

    <bean id="bookDao" class="com.gientech.tx.xml.dao.BookDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>


    <!-- 当前myAdvice类应用到txPoint expression所指代的类/方法上 -->
    <aop:config>
        <!-- 匹配com.gientech.tx.xml类下面的所有类,所有方法。 -->
        <aop:pointcut id="txPoint" expression="execution(* com.gientech.tx.xml.*.*.*(..))"/>
        <aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"></aop:advisor>
    </aop:config>


    <!-- -->
    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="checkout" propagation="REQUIRED" />
            <tx:method name="updateStock" propagation="REQUIRES_NEW" />
        </tx:attributes>
    </tx:advice>

 </beans>

1.2 db配置文件

jdbc.username=root
jdbc.password=123456
jdbc.url=jdbc:mysql://localhost:3306/gientechtest?useSSL=false
jdbc.driverClassName=com.mysql.jdbc.Driver

1.3 service

package com.gientech.tx.xml.service;

import com.gientech.tx.xml.dao.BookDao;

public class BookService {

    BookDao bookDao;

    public BookDao getBookDao() {
        return bookDao;
    }

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    /**
     * 结账:传入哪个用户买了哪本书
     * @param username
     * @param id
     */
    public void checkout(String username,int id){

        try {
            bookDao.updateStock(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
//        for (int i = 1 ;i>=0 ;i--)
//            System.out.println(10/i);
//        int price = bookDao.getPrice(id);
//        bookDao.updateBalance(username,price);
    }

}

1.4 dao

package com.gientech.tx.xml.dao;

import org.springframework.jdbc.core.JdbcTemplate;

public class BookDao {

    JdbcTemplate jdbcTemplate;

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    /**
     * 减去某个用户的余额
     * @param userName
     * @param price
     */
    public void updateBalance(String userName,int price){
        String sql = "update account set balance=balance-? where username=?";
        jdbcTemplate.update(sql,price,userName);
    }

    /**
     * 按照图书的id来获取图书的价格
     * @param id
     * @return
     */
    public int getPrice(int id){
        String sql = "select price from book where id=?";
        return jdbcTemplate.queryForObject(sql,Integer.class,id);
    }

    /**
     * 减库存,减去某本书的库存
     * @param id
     */
    public void updateStock(int id){
        String sql = "update book_stock set stock='stock-1' where id=?";
        jdbcTemplate.update(sql,id);
//        for (int i = 1 ;i>=0 ;i--)
//            System.out.println(10/i);
    }

}

1.5 启动文件

public class TxTest {
    public static void main(String[] args) {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"d:\\code");
        ApplicationContext context = new ClassPathXmlApplicationContext("tx.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        bookService.checkout("zhangsan",1);
        System.out.println();
    }
}

2 Transaction 过程解析

2.1 加载XML 定义信息。

在obtainFreshBeanFactory()方法中,加载xml配置文件的属性值到当前工厂中,在parseCustomElement(ele, null) 中,
ConfigBeanDefinitionParser.parseAdvisor方法解析Advisor标签时,创建类对象,名称spring会按照一定规则进行创建,如图所示
解析Advisor标签

2.1.2 解析<tx: 标签

<tx开始的标签是在delegate.parseCustomElement(ele)方法中进行解析,在BeanDefinitionParserDelegate.parseCustomElement方法中,第一步根据命名空间获取NamespaceHandler,在spring-tx\src\main\resources\META-INF\spring.handlers文件中进行具体的配置,

xml配置文件加载完成之后,容器中的对象如图,
xml文件加载完成

2.2 调用invokeBeanFactoryPostProcessors(beanFactory)

此时,加载的xml配置文件属性值并未填充为实际值,调用后,会填充为真实值。下图为替换之前的值
xml属性填充之前

XML文件中变量值替换完成之后如图:
xml变量填充后

2.3 注册BeanPostProcessor

registerBeanPostProcessors(beanFactory) 作用是注册BeanPostProcessor,此时会创建动态代理自动创建器AspectJAwareAdvisorAutoProxyCreator,在执行前,一级缓存中没有AspectJAwareAdvisorAutoProxyCreator对象,执行完成后AspectJAwareAdvisorAutoProxyCreator对象生成。执行前如下图。
创建动态代理自动创建器之前

执行完成后AspectJAwareAdvisorAutoProxyCreator对象生成,一级缓存截图如下。
创建动态代理自动创建器之后

2.4 初始化Advisor

创建DefaultBeanFactoryPointcutAdvisor对象,但未创建对应属性对象,内存截图如下:
未赋值之前

advice-ref="myAdvice" 对应的是adviceBeanName,是RuntimeBeanNameReference 对象,名称创建完成,pointcut-ref="txPoint" 对应的是pointcut,对象创建完成截图如下:
pointcut创建完成

在此例中,bookservice,bookdao也是需要被动态代理的。动态代理对象创建完成之后截图如下:
动态代理对象

标签:xml,事务,Transaction,int,bookDao,public,jdbcTemplate,id
From: https://www.cnblogs.com/zgcy123456/p/18239657

相关文章

  • Spring (73)Spring项目中的事务管理最佳实践
    Spring项目中的事务管理是确保数据一致性和完整性的关键组成部分。Spring提供了一套灵活而强大的事务管理框架,允许开发者以声明式和编程式两种方式来管理事务。为了确保高效和安全的事务管理,遵循最佳实践是非常重要的。下面深入探讨Spring事务管理的最佳实践,并结合源码分析......
  • 事务
    一、事务的四大特性原子性(Atomicity)事务包含的所有数据库操作要么全部成功,要不全部失败回滚。一致性(Consistency)一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。一致性规定事务提交前后只存......
  • MySQL索引、事务与存储引擎
    目录1.索引介绍(1)工作方式(2)创建索引的依据2.索引类型(1)普通索引(2)唯一索引(3)主键索引(4)多列组合索引(单列索引与多列索引)(5)全文索引(FULLTEXT)(6)删除和查看索引以及各字段的含义(1)删除索引(2)查看索引(3)各字段的含义3.遇到select查询语句执行速度慢该怎么办?4.事务介绍(1)事务的ACID特性(2)隔离......
  • 提交数据库事务时报告了一个错误,但无法确定该事务在数据库服务器上是成功还是失败
    客户的库偶尔报下面这个错误:Anerrorwasreportedwhilecommittingadatabasetransactionbutitcouldnotbedeterminedwhetherthetransactionsucceededorfailedonthedatabaseserver日志里记超时,而程序里设置的超时时间是3小时,这里3-5分钟就超时了......
  • MySQL进阶知识之视图、触发器、事务
    【一】MySQL进阶知识之视图【1】视图介绍(1)什么是视图视图就是通过查询得到一张虚拟表,然后保存下来,下次可以直接使用视图也是一张表在计算机科学中,视图(View)是一种虚拟表,其内容是一个或多个基本表的查询结果。视图基于数据库中的数据,通过定义查询语句来构建,并在需要时动......
  • Spring框架声明是事务
    声明式事务(DeclarativeTransactionManagement)是Spring框架提供的一种对程序事务进行管理的方式。这种管理方式的核心思想是采用声明的方式(通常是在配置文件中声明,而非在代码中硬编码)来处理事务,从而简化开发过程,降低开发者处理复杂事务的难度。在声明式事务中,开发者通过注解(如@T......
  • 凤凰架构记02-事务
    事务的基本特性A原子性:一系列操作为一个原子,都成功或都撤销I隔离性:不同操作之间读写数据相互独立,不会彼此影响D持久性:成功提交的数据都会被持久化,不会丢失C一致性:一致性为最终目的,所有事物处理最终的数据状态保持一致 内部一致性:单数据源有确定并发事务的读写顺序外部一致......
  • 【总线】AXI4第二课时:深入AXI4总线的基础事务
                    大家好,欢迎来到今天的总线学习时间!如果你对电子设计、特别是FPGA和SoC设计感兴趣,那你绝对不能错过我们今天的主角——AXI4总线。作为ARM公司AMBA总线家族中的佼佼者,AXI4以其高性能和高度可扩展性,成为了现代电子系统中不可或缺的通信桥梁。......
  • .NET Core 3.x 基于AspectCore实现AOP,实现事务、缓存拦截器
    最近想给我的框架加一种功能,就是比如给一个方法加一个事务的特性Attribute,那这个方法就会启用事务处理。给一个方法加一个缓存特性,那这个方法就会进行缓存。这个也是网上说的面向切面编程AOP。AOP的概念也很好理解,跟中间件差不多,说白了,就是我可以任意地在方法的前面或后面添加代码......
  • 关于RuntimeException与事务
    1.spring的默认回滚策略当采用@Transactional注解方法抛出RuntimeException时,spring会默认回滚事务对于检查型异常(即不是RuntimeException子类或其子类),spring默认不会回滚,除非明确指定@Transactional(rollbackFor=MyException.class)2.简化代码:使用运行时异常不再需要为每一......