11.spring基于XML配置声明式事务控制

spring声明式事务控制XML配置

spring提供了事务控制,具体的步骤如下

一、基于XML的声明式事务配置的基本步骤

这里先介绍声明式事务控制的主要配置步骤,整个项目的环境介绍将放在下第二节介绍

1). 配置事务管理器

事务管理器相当于代理对象,内部封装了通知方法,需要注入数据源(数据源的配置在完整项目中介绍)

DataSourceTransactionManager类中有个属性nestedTransactionAllowed ,表示允许【嵌套事务】,基于此原理,然后再基于切面编程(被代理方法前后增强),实现嵌套事务!



    

2). 配置事务通知

1.首先得确保导入事务的约束

  1. 官网
  2. Data Access
  3. ctrl f 搜索 xmlns:tx



    
    

    

3). 配置AOP中通用切入点表达式并建立事务通知和切入点表达式的对应关系



    
    
    
    

4). 配置事务的属性

在事务的通知tx:advice标签内部陪

1.事务属性对应的属性

  1. name: 指定切入点方法,属于之前配置的切入点表达式;可以使用通配符进行匹配,
  2. isolation: 用于指定事务的隔离级别。默认值是 DEFAULT ,表示使用数据库的默认隔离级别
  3. propagation: 用于指定事务的传播行为。默认值是 REQUIRED ,表示一定会有事务,增删改的选择。查询方法可以选择 SUPPORTS.
  4. read-only: 用于指定事务是否只读。只有查询方法才能设置为 true .默认值是 false ,表示读写
  5. timeout: 用于指定事务的超时时间,默认值是 -1,表示永不超时。如果指定了数值,以秒为单位。
  6. rollback-for: 用于指定一个异常,当产生该异常时,事务回滚;产生其他异常时,事务不会滚;没有默认值(设置值),任何异常都会回滚。
  7. no-rollback-for: 用于指定一个异常,当产生该异常时,事务不会滚;产生其他异常时事务回滚;没有默认值(设置值),任何异常都会回滚


    
        
        
        
        
    

二、完整项目代码

1). 项目结构


11.spring基于XML配置声明式事务控制_第1张图片
spring声明式事务控制XML配置项目结构.png

2). maven坐标


        
            mysql
            mysql-connector-java
            5.1.41
        
        
            org.springframework
            spring-beans
            5.0.3.RELEASE
        
        
            org.springframework
            spring-context
            5.0.3.RELEASE
        
        
            org.springframework
            spring-core
            5.0.3.RELEASE
        
        
            org.springframework
            spring-expression
            5.0.3.RELEASE
        
        
            org.springframework
            spring-aop
            5.0.3.RELEASE
        
        
            org.springframework
            spring-test
            5.0.2.RELEASE
        
        
            junit
            junit
            4.12
            test
        
        
        
            org.aspectj
            aspectjweaver
            1.8.7
        
        
            org.springframework
            spring-jdbc
            5.0.2.RELEASE
        
    

3). applicationContext.xml核心配置文件




    
    
        
    

    
        
    

    
    
        
        
        
        
    

    
    
        
    

    
    
        
            
            
            
            
        
    

    
    
        
        
        
        
    

4). Account pojo/javaBean

省略get/set/toString方法; 数据库中对应的表为account;对应的字段名与该Bean字段名相同。

public class Account {
    private Integer id;
    private String name;
    private Float money;
    ...

5). dao持久层代码

import com.itheima.domain.Account;
import java.sql.SQLException;
public interface AccountDao {

    /** 根据id查询账户的余额 */
    public Account queryMoney(Integer id) throws SQLException;

    /** 根据id更新账户的余额 */
    public int updateMoney(Integer id, Float money) throws SQLException;
}
import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import java.sql.SQLException;
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

    /** @事务
     * 根据id查询账户的余额,将异常显示抛出 */
    @Override
    public Account queryMoney(Integer id) throws SQLException {
        return super.getJdbcTemplate().queryForObject("select money from account where id = ?",
                new BeanPropertyRowMapper(Account.class), id);
    }

    /** @事务
     * 根据id更新账户的余额, 将异常显示抛出 */
    @Override
    public int updateMoney(Integer id, Float money) throws SQLException {
        return super.getJdbcTemplate().update("update account set money = ? where id = ?",
                money, id);
    }
}

6). service业务层代码

public interface AccountService {
    /** 转账业务 */
    public boolean transfer(Integer fromId, Integer toId, Float money) throws Exception;
}
package com.itheima.service.impl;
import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    /** @事务
     * 转账业务 */
    @Override
    public boolean transfer(Integer fromId, Integer toId, Float money) throws Exception {
        // 1. 查询原账户余额
        Account fromMoney = accountDao.queryMoney(fromId);

        if (fromMoney.getMoney() < money) {
            throw new RuntimeException("账户余额不足,无法完成转账");
        }

        // 2. 查询被转入账户的余额
        Account toMoney = accountDao.queryMoney(toId);

        // 3. 扣除原账户的money
        accountDao.updateMoney(fromId, fromMoney.getMoney() - money);

        // 显示抛出一个异常。
        int a = 8 / 0;

        // 4. 添加被转入账户的余额
        accountDao.updateMoney(toId, toMoney.getMoney() + money);

        return true;
    }
}

7). 测试代码

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class MyTest {
    @Autowired
    private ApplicationContext ac;

    /** 转账测试 */
    @Test
    public void testTransfer() throws Exception {
        AccountService service = (AccountService)ac.getBean("accountService");
        boolean res = service.transfer(4, 2, 1000F);
        System.out.println(res);
    }
}

你可能感兴趣的:(11.spring基于XML配置声明式事务控制)