使用方法

1. 添加相关jar包或依赖——数据源、数据库驱动、mysql或spring-jdbc等,这里以spring-jdbc为例;

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

2. 数据库连接参数,一般单独写在properties或yaml配置文件中;

3. 编写数据库访问层组件(dao)和业务逻辑层组件(service),且在service层需要事务管理的方法上加@Transactional注解;

4. 在容器中注册数据源、数据库操作模板、事务管理器,以及步骤3中的组件;

5. 在容器中开启基于事务的注解,即在容器配置类上加@EnableTransactionManagement注解。

 

注:

1. 在容器配置类(即添加了@Configuration注解的类)中,可以在一个方法中获取其他方法注册的bean实例,方法有两种

    |-在参数列表中直接接收;

    |-在方法体中调用另一个方法,这种情况下多次调用容器配置类中的方法,并不会反复创建实例,而是从容器中获取实例;

2. 如果service层使用了try/catch语句,会导致发生异常时之前的操作无法回滚,为了避免这种情况,需要在catch字句中加TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 表示捕获异常后仍然回滚。

 

下面是一个使用spring-jdbc访问数据库的事务demo

pom文件

<!--spring数据库操作模板-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.1.16.RELEASE</version>
</dependency>
<!--数据源,由于只是测试事务的demo,用的c3p0-->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.4</version>
</dependency>
<!--数据库驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.15</version>
</dependency>

 

数据库配置文件

jdbc.url=jdbc:mysql://127.0.0.1:3306/test
jdbc.username=root
jdbc.password=123456
jdbc.driverClass=com.mysql.jdbc.Driver

 

容器配置类

/**
 * 容器配置类
 * @EnableTransactionalManagement注解的意义是开启基于注解的事务,即使方法上的@Transactional注解生效
*/ @Configuration @ComponentScan(basePackages = {"cn.monolog.service", "cn.monolog.dao"}) @PropertySource(value = "classpath:/datasource.properties") @EnableTransactionManagement public class TxBeanConfig { //从配置文件中注入属性 @Value(value = "${jdbc.username}") private String username; @Value(value = "${jdbc.password}") private String password; @Value(value = "${jdbc.driverClass}") private String driverClass; @Value(value = "${jdbc.url}") private String url; //注册数据源 @Bean(name = "dataSource") public DataSource dataSource() throws PropertyVetoException { //创建数据源实例 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); //属性注入 comboPooledDataSource.setUser(this.username); comboPooledDataSource.setPassword(this.password); comboPooledDataSource.setDriverClass(this.driverClass); comboPooledDataSource.setJdbcUrl(this.url); //返回 return comboPooledDataSource; } //注册spring的数据库操作模板 @Bean(name = "jdbcTemplate") public JdbcTemplate jdbcTemplate() throws PropertyVetoException { //从容器中获取数据源 // --注:spring对配置类(即加了@Configuration的类)有特殊处理, // 当多次调用注册方法时,并不是每次都会创建新bean,而是会从容器中获取bean DataSource dataSource = this.dataSource(); //创建模板 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); //返回模板 return jdbcTemplate; } //注册事务管理器 @Bean(name = "transactionManager") public PlatformTransactionManager transactionManager() throws PropertyVetoException { //从容器中获取数据源 DataSource dataSource = this.dataSource(); //创建事务管理器实例 DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource); //返回 return dataSourceTransactionManager; } }

 

数据库访问层组件

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
/**
 * 数据库访问层组件
 * 用于测试事务
 */
@Repository
public class VariationDao {

    //从容器中自动注入spring数据库操作模板
    @Autowired
    @Qualifier("jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    /**
     * 创建一条数据
     */
    public void create(String staffId, Integer alloted) {
        //编写sql语句
        String sql = "insert into c_variation_config (staff_id, alloted) values (?, ?)";
        //执行sql语句
        this.jdbcTemplate.update(sql, staffId, alloted);
    }
}

 

业务逻辑层组件

import cn.monolog.dao.VariationDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 业务逻辑层组件
 * 用于测试事务
 */
@Service
public class VariationService {

    //从容器中自动注入dao层组件
    @Autowired
    @Qualifier("variationDao")
    private VariationDao variationDao;

    /**
     * 创建一条数据
     */
    @Transactional
    public void create(String staffId, Integer alloted) {
        //执行
        this.variationDao.create(staffId, alloted);
        //手动制造异常,由于加了事务,上一条语句产生的数据库更新会被回滚
        int i = 10 / 0;
    }
}

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄