Spring中的事务控制:

spring中的事务控制分为两种,一种是声明式事务,一种式编程式事务,编程式事务于spring中解耦的核心思想有些冲突,所以实际开发中一般采用声明式事务。

1.前期准备:

开发环境:
	IDAD 2.18.3
	jdk 1.8
	maven 3.5
	以及spring所需要的各类jar依赖
	
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.7</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>MySQL</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.18</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
</dependencies>

既然式用纯注解的方式来编写aop和事务控制,那么我们就应该把相应的配置工具类准备好
先创建一个类,只声明是spring的配置类,打上@Configuration注解等

@ComponentScan( "welness")
@Import({JDBCTemplateConfig.class,TransactionManagerConfig.class})//导入其他的配置类
@Configuration//本类作为spring的配置核心类
@EnableAspectJAutoProxy//开启spring的aop支持
@EnableTransactionManagement//开始spring的注解支持
public class SpringConfiguration {
}

配置切面类

@Component("aspect")//加入spring的容器中
@Aspect//声明此类为切面
public class AspectLogger {

    @Pointcut("execution(* welness.service.utils.*.*(..))")
    private void pt() {
    }

    @Around("pt()")
    public void printLog(ProceedingJoinPoint pjp) {
       /* Object[] args = pjp.getArgs();
        Object rtValue = null;*/
        try {
            System.out.println("开始记录日志");
            pjp.proceed();
            System.out.println("记录日志成功");
        } catch (Throwable throwable) {
            System.out.println("事务发生异常,开始回滚");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//这里抛出的是Throwable类型的异常,不是Execption类型的异常,需要手动回滚
            throwable.printStackTrace();
        }
    }

}

这里注意,我在catch代码块里面手动回滚了,因为spring中的事务回滚只有抛出uncheckedExecption以及RuntimeExecption类型的异常才能事务回滚,在环绕通知里面抛出的是Throwable类型的异常,所以自动回滚不能正常进行。

配置事务管理类

PlatformTransactionManager是一个接口,他继承了TransactionManager,提供了对事务的控制

public class TransactionManagerConfig {

    @Bean
    public PlatformTransactionManager createTransactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

数据库连接配置

@PropertySource("jdbcConfig.properties")
public class JDBCTemplateConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;



    @Bean("jdbcTemplate")
    public JdbcTemplate createJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
    @Bean("dataSource")
    public DataSource createDataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);

        return dataSource;

    }
}

业务层实现类代码
要加上Transactional声明事务的属性
SUPPORTS属性是如果当前有事务,就加入这个事务,如果没有就按无事务的状态进行
REQUIRED属性是如果当前有事务,就按当前事务进行,如果没有事务,就创建一个和事务

@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
@Service("accountService")
public class AccountImpl implements IAccountService {
    @Autowired
    private IAccountDao dao;

    @Override
    public List<Account> findAllAccount() {
        return dao.findAllAccount();
    }

    @Override
    public Account findById(int id) {
        return dao.findById(id);
    }

    @Override
    public void saveAccount(Account account) {
        dao.saveAccount(account);
    }

    @Override
    public void updateAccount(Account account) {
        dao.updateAccount(account);
    }

    @Override
    public void deleteAccount(Account account) {
        dao.deleteAccount(account);
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void transfer(String source, String target, float money) {
            Account Source = dao.findByName(source);

            Account Target = dao.findByName(target);

            Source.setMoney(Source.getMoney()-money);

            Target.setMoney(Target.getMoney()+money);

            dao.updateAccount(Source);
            dao.updateAccount(Target);

            int i  = 9/0;//生成异常,看看事务是否是正常运行
    }
}

这里是测试之前的数据
【spring】aop和事务控制整合(基于注解配置)_java
aop什么的都正常,也监测出来异常。
【spring】aop和事务控制整合(基于注解配置)_分享_02
数据库的数据没有变,证明事务成功了。
【spring】aop和事务控制整合(基于注解配置)_spring_03