首页 > 其他分享 >声明式事务之XML实现方式

声明式事务之XML实现方式

时间:2023-06-16 19:32:18浏览次数:35  
标签:XML 事务 声明 Account powernode com import actno public

1. 配置步骤:  135

● 第一步:配置事务管理器

● 第二步:配置通知

● 第三步:配置切面

记得添加aspectj的依赖:

<!--aspectj依赖-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
  <version>6.0.0-M2</version>
</dependency>

Spring配置文件如下:

记得添加aop的命名空间。

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/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.powernode</groupId>
    <artifactId>course31</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>jar</packaging>

    <!--仓库-->
    <repositories>
        <!--spring里程碑版本的仓库-->
        <repository>
            <id>repository.spring.milestone</id>
            <name>Spring Milestone Repository</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

    <!--依赖-->
    <dependencies>
        <!--spring context-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
        <!--spring aspects依赖 AspectJ的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
        <!--spring jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <!--德鲁伊连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.13</version>
        </dependency>
        <!--@Resource注解-->
        <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

</project>

spring.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: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/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.powernode.bank"/>

    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring6"/>
        <property name="username" value="root"/>
        <property name="password" value="lzl"/>
    </bean>

    <!--配置JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

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

    <!--配置通知,具体的增强代码。135-->
    <!--注意:在通知当中要关联事务管理器。-->
    <tx:advice id="txAdvice" transaction-manager="txManager">
<!--        配置相关的通知属性-->
        <tx:attributes>
            <tx:method name="transfer" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<!--            上面的transfer把名字写死了,有时候不方便,以下是举例的模糊匹配-->
            <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
            <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
            <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
            <tx:method name="modify*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
            <tx:method name="query*" read-only="true"/>
            <tx:method name="select*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

<!--    配置切面-->
    <aop:config>
<!--        切点-->
        <aop:pointcut id="txPointcut" expression="execution(* com.powernode.bank.service..*(..))"/>
        <!--切面 = 通知 + 切点-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>

</bean>

pojo类Account

package com.powernode.bank.pojo;

/**
 * 银行账户类  119
 **/
public class Account {
    private String actno;
    private Double balance;

    @Override
    public String toString() {
        return "Account{" +
                "actno='" + actno + '\'' +
                ", balance=" + balance +
                '}';
    }

    public Account() {
    }

    public Account(String actno, Double balance) {
        this.actno = actno;
        this.balance = balance;
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }
}

dao接口AccountDao

package com.powernode.bank.dao;

import com.powernode.bank.pojo.Account;

/**
 * 专门负责账户信息的CRUD操作。   119
 * DAO中只执行SQL语句,没有任何业务逻辑。
 * 也就是说DAO不和业务挂钩。
 */
public interface AccountDao {
    /**
     * 根据账号查询账户信息
     * @param actno
     * @return
     */
    Account selectByActno(String actno);

    /**
     * 更新账户信息。
     * @param act
     * @return
     */
    int update(Account act);

}

dao接口实现类AccountDaoImpl

package com.powernode.bank.dao.impl;

import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.pojo.Account;
import jakarta.annotation.Resource;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
 * AccountDao接口实现类   119
 **/
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {

    @Resource(name = "jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    @Override
    public Account selectByActno(String actno) {
        String sql = "select actno, balance from t_act where actno = ?";
        Account account = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Account.class), actno);
        return account;
    }

    @Override
    public int update(Account act) {
        String sql = "update t_act set balance = ? where actno = ?";
        int count = jdbcTemplate.update(sql, act.getBalance(), act.getActno());
        return count;
    }

}

业务层接口AccountService

package com.powernode.bank.service;

import com.powernode.bank.pojo.Account;

/**
 * 业务接口  119
 **/
public interface AccountService {

    /**
     * 转账业务方法
     * @param fromActno 从这个账户转出
     * @param toActno 转入这个账户
     * @param money 转账金额
     */
    void transfer(String fromActno, String toActno, double money);

}

业务层接口实现类AccountServiceImpl

package com.powernode.bank.service.impl;

import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.pojo.Account;
import com.powernode.bank.service.AccountService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 业务层实现类  119
 **/
@Service("accountService")
public class AccountServiceImpl implements AccountService {

    @Resource(name = "accountDao")
    private AccountDao accountDao;

    // 控制事务,因为在这个方法中要完成所有的转账业务。
    @Override
    public void transfer(String fromActno, String toActno, double money) {

        // 第一步:开启事务

        // 第二步:执行核心业务逻辑
        // 查询转出账户的余额是否充足
        Account fromAct = accountDao.selectByActno(fromActno);
        if (fromAct.getBalance() < money) {
            throw new RuntimeException("余额不足!!!");
        }
        // 余额充足
        Account toAct = accountDao.selectByActno(toActno);

        // 将内存中两个对象的余额先修改。
        fromAct.setBalance(fromAct.getBalance() - money);
        toAct.setBalance(toAct.getBalance() + money);

        // 数据库更新
        int count = accountDao.update(fromAct);

         count += accountDao.update(toAct);

        if(count != 2) {
            throw new RuntimeException("转账失败,联系银行!");
        }

        // 第三步:如果执行业务流程过程中,没有异常。提交事务
        // 第四步:如果执行业务流程过程中,有异常,回滚事务。

    }
}

测试

package com.powernode.bank.test;

import com.powernode.bank.service.AccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 声明式事务之XML实现方式
 * 测试  135
 **/
public class BankTxTest {

    @Test
    public void testNoAnnotation(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
        try {
            accountService.transfer("act-001", "act-002", 10000.0);
            System.out.println("转账成功");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

声明式事务之XML实现方式_spring

在AccountServiceImpl的transfer方法模拟异常

// 模拟异常
        String s = null;
        s.toString();

声明式事务之XML实现方式_bc_02

声明式事务之XML实现方式_声明事务之xml方式_03

钱没有消失,事务生效

标签:XML,事务,声明,Account,powernode,com,import,actno,public
From: https://blog.51cto.com/u_15784725/6501952

相关文章

  • 用声明式宏解析 Rust 语法
    在上一篇Rust声明式宏中的Metavariables有哪些的基础上,今天尝试解析一下Rust中的几种item。我们知道一个crate是由item组成的,每一个fnstructenumimplmod等定义都是一个item,这篇文章就简单解析一下Function和structFunction先看一个最简单的函数fnfoo(......
  • Go Redis 管道和事务之 go-redis
    GoRedis管道和事务之go-redisGoRedis管道和事务官方文档介绍Redispipelines(管道)允许一次性发送多个命令来提高性能,go-redis支持同样的操作,你可以使用go-redis一次性发送多个命令到服务器,并一次读取返回结果,而不是一个个命令的操作。GoRedis管道和事务:https://red......
  • STUFF和FOR XML PATH('')
    初始状态:执行代码:SELECTSTUFF((SELECT','+Test_TableFROMdbo.Test_Table_MappingWHEREID=1570FORXMLPATH('')),1,1,'')text 显示结果 在SQLServer中,stuff()函数用于从源字符串中删除给定长度的字符序列,并从指定的起始索引插入给定的字符序列。STUFF(so......
  • java中xml和json转换
    packagecom.lbdz.bsf.util;importnet.sf.json.JSONObject;importnet.sf.json.JSONSerializer;importnet.sf.json.xml.XMLSerializer;/***xml和json转换*/publicclassXMLUtils{/***xml转化为字符串*@paramxml*@returnstr......
  • 事务操作
    方式一:set@@autocommit=0;//设置为手动提交//事务执行成功后调用commit提交事务commit;//如果执行失败使用rollback回滚rollback;方式二:starttransaction或begin;--开启事务commit;rollback;事务隔离级别:未提交读,事务中发生了修改,即使没有提......
  • Spring事务基础介绍
    事务本文只介绍声明式事务管理,即使用AOP实现,使用@Transactional开始事务事务角色事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法接口介绍PlatformTransactionManager:Spring事务......
  • log4j.xml示例
    <?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPElog4j:configurationSYSTEM"log4j.dtd"><log4j:configurationxmlns:log4j="http://jakarta.apache.org/log4j/"debug="false"><ap......
  • XML反序列化笔记
    反序列化枚举类型public银行卡类型marcaTarjeta{get;set;}publicenum银行卡类型{[XmlEnum(Name="0")]UnKnown=0,[XmlEnum(Name="1")]VISA=1,[XmlEnum(Name="2")]MASTERC......
  • Python - 函数声明中的 : 和 -> 符号的含义
     函数注释包括:: 标记给函数参数打注释的意思。-> 标记给函数返回值打注释的意思。 例子:#代码:defdd(w:list)->int:returnw[0]+w[1]#调用:dd([1,2])#输出:3 解释:: 表示参数w应该传入list类型的值,但只是注释(在你的代码里,你传入其他的类型,只要代码......
  • 【数据库】事务与锁
    参考:https://dev.mysql.com/doc/refman/8.0/en/innodb-autocommit-commit-rollback.html autocommit,Commit,andRollbackInInnoDB,alluseractivityoccursinsideatransaction.Ifautocommitmodeisenabled,eachSQLstatementformsasingletransactionon......