当前位置: 首页 > 图灵资讯 > 技术篇> 声明式事务之XML实现方式

声明式事务之XML实现方式

来源:图灵教育
时间:2023-06-17 13:55:25

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>    <!--Jdbctemplatet配置-->    <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;    }}
Accoundao接口
package com.powernode.bank.dao;import com.powernode.bank.pojo.Account;/** * CRUD操作专门负责账户信息。   119 * SQL语句只在DAO中执行,没有任何业务逻辑。 * 也就是说,DAO不与业务挂钩。 */public interface AccountDao {    /**     * 根据账户查询账户信息查询账户信息     * @param actno     * @return     */    Account selectByActno(String actno);    /**     * 更新帐户信息。     * @param act     * @return     */    int update(Account act);}
实现AccountDaoImplaodao接口
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 = ? where actno = ?";        int count = jdbcTemplate.update(sql, act.getBalance(), act.getActno());        return count;    }}
Accountservicent业务层接口
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);}
AccountServiceimple实现业务层接口
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(转账失败,联系银行!= 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实现方式_声明事务之xml方式

在Accountserviceimpl的transfer模拟异常

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

 

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

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

钱没有消失,事务生效了