一.入门知识点
@Transactional注解: 会产生代理对象,实现功能的改变和增强Object target : 目标对象
Proxy :代理对象
如果是CGLIB的动态代理,会在代理对象中 存在一个目标对象的属性例如
Class Proxy{
Object target;
}
在前置执行后,会调用target对象的XX方法,执行对应逻辑,后面再执行后置动作
二.在配置类上要开启事务支持功能
@EnableTransactionManagement
三.对应代码实现
package com.transaction.wang;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@ComponentScan("com.transaction.wang")
@EnableTransactionManagement
@Configuration
public class TransactionConfig {
@Bean
public PlatformTransactionManager platformTransactionManager(){
DataSourceTransactionManager manager = new DataSourceTransactionManager();
manager.setDataSource(dataSource());
return manager;
}
@Bean
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(dataSource());
}
@Bean
public DataSource dataSource(){
//DataSource ds = new PooledDataSource("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/wang_learn","root","root");
DriverManagerDataSource dds = new DriverManagerDataSource
("jdbc:mysql://localhost:3306/wang_learn","root","root");
return dds;
}
}
package com.transaction.wang;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestTx {
public static void main(String[] args) throws Exception{
System.out.println("args = " + args);
AnnotationConfigApplicationContext
app = new AnnotationConfigApplicationContext(TransactionConfig.class);
System.out.println("app = " + app);
DbDao bean = app.getBean(DbDao.class);
bean.insertOneData();
}
}
package com.transaction.wang;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
public class DbDao {
@Autowired
private JdbcTemplate jdbcTemplate;
// rollbackFor=Exception.class
@Transactional(rollbackFor=Exception.class)
public void insertOneData() throws Exception {
String sql = "INSERT INTO t_wang_tx(my_id,my_var,my_int) VALUES(300,'qqq',2)";
jdbcTemplate.execute(sql);
throw new Exception("事务异常了");
//throw new NullPointerException();
}
}
执行结果图:
可以观察到库中并没有数据进入.
四:小结
在模拟过程,遇到了事务失效的问题,就是手动抛出异常后,数据任然入库了,在尝试后发现是@Transaction注解上没有加上rollbackFor = Exception.class导致!
此外,如果去掉配置类上的@Configuration注解,一样会导致事务失效,这个是由于dataSource对象不是同一个(非单例),导致事务对应的connection对象 和 执行sql的jdbcTeplate里面的connection对象不是同一个导致!这里结合spring学习第三篇一起理解!spring源码一.(3)@Configuration注解理解_ccwangwang的博客-CSDN博客