聊一聊Spring中的Transaction基本实现
聊一聊Spring中的 Transaction基本实现
我们知道加一个 org.springframework.transaction.annotation.Transactional 注解便可以让改方法实现事务管理(提交/回滚), 但是我们知道一个如何用编码的方式实现事务如何回滚的 . 抛开动态代理 , 其实事务就是动态代理实现, 但是不是我们的重点 , 我们要讲讲他为啥只支持单个数据源 还有不支持 异步操作(这里的意思是在事务里开启一个新线程执行业务)前言
一般操作都是下面这样子 , 基本流程 // 获取连接 Connection connection = dataSource1.getConnection(); try { // 设置事务隔离等级 connection.setTransactionIsolation(3); // 设置自动提交为false connection.setAutoCommit(false); // 业务 PreparedStatement statement = connection.prepareStatement(); statement.execute(); // 成功提交 connection.commit(); } catch (Exception e) { // 异常rollback connection.rollback(); } finally { // 设置为true connection.setAutoCommit(true); // 关闭 connection.close(); }
所以Spring帮助我们做的就是这个, 那么它一定也是这么实现的 .
如何启动事务呢 ,
首先需要加入依赖 org.springframework spring-tx 5.0.8.RELEASE
SpringBoot 可以使用这个 org.springframework.transaction.annotation.EnableTransactionManagement ,对于XML配置可以去看看这个类, 他会教你咋配置 .
方法控制是依靠 @Transactional(transactionManager ="TransactionManager") ,
然后我们需要自己自定义实现一个 org.springframework.transaction.PlatformTransactionManager Bean , 告诉spring事务处理的使用哪个
那么为啥加了个注解就会自动给你管理事务了呢 , 他难道不是这么做的吗.
其实看 org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration 这个地方@Configuration // 前提你只有一个数据源 @ConditionalOnSingleCandidate(DataSource.class) static class DataSourceTransactionManagerConfiguration { ........... // 这里PlatformTransactionManager前提你不实现 @Bean @ConditionalOnMissingBean(PlatformTransactionManager.class) public DataSourceTransactionManager transactionManager(DataSourceProperties properties) { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource); return transactionManager; } }
在你单数据源的情况下, 同时自动注入情况下, 他会默认给你生成一个 DataSourceTransactionManager
所以默认情况下, 就是走这个, 现在我们绝地不看这个 . 我们要自己实现 . 正文"
我们的问题 . @Configuration public class DataConfig { @Bean("datasource1") public DataSource dataSource() { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } MysqlDataSource dataSource = new MysqlDataSource(); dataSource.setURL("jdbc:mysql://localhost:3306/jpa?useSSL=false"); dataSource.setUser("root"); dataSource.setPassword("123456"); return dataSource; } // 还有一个 datasource2 @Bean(name = "TransactionManager1") public DataSourceTransactionManager clusterTransactionManager(@Qualifier("datasource1") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } // 还有一个 TransactionManager2,地方有限 }
我们定义俩数据源, 其中就需要俩 DataSourceTransactionManager
那么写我们的service @Service public class TestService { @Autowired @Qualifier("datasource1") private DataSource dataSource1; @Transactional public void test() throws SQLException { Connection connection1 = dataSource1.getConnection(); Statement statement1 = connection1.createStatement(); int i = statement1.executeUpdate("INSERT INTO go_user (`name`,`password`) VALUES ("name12345","p5")"); System.out.println("成功 : " + i); int x = 1 / 0; // 连接二也是如此 . 懒得写 , 我测试的时候写的俩数据源 } }
这样子启动绝对会GG , 因为你没指定有哪个 TransactionManager .
那么我们怎么做, @Transactional(transactionManager = "TransactionManager2")
但是事务处理的时候 org.springframework.jdbc.datasource.DataSourceTransactionManager#doRollback @Override protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); try { con.rollback(); } catch (SQLException ex) { } }
他有一个 Connection , 那么不和我们的connection一样 , 那么绝对回滚不了哇. 因为你不是一个连接, 所以根本题绝对提交成功了 , 那么为啥Mybatis 可以呢 . 所以借鉴一下,
我们看MyBatis的实现 org.mybatis.spring.transaction.SpringManagedTransaction 在这里, 这里缩进不了了 , 他的tab是俩空格, 我是四个, 哎 . 就这么看吧 @Override public Connection getConnection() throws SQLException { // 连接为null if (this.connection == null) { // 打开一个 openConnection(); } return this.connection; } private void openConnection() throws SQLException { // 获取Connection , 原来如此 这么获取 this.connection = DataSourceUtils.getConnection(this.dataSource); this.autoCommit = this.connection.getAutoCommit(); this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource); }
所以就是在获取这里 DataSourceUtils ->org.springframework.jdbc.datasource.DataSourceUtils#getConnection public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException { try { return doGetConnection(dataSource); } catch (SQLException ex) { /// } }
doGetConnection(dataSource) ->org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection public static Connection doGetConnection(DataSource dataSource) throws SQLException { // 获取一个 ConnectionHolder 持有对象 . 奥原来这样子 . // 通过 TransactionSynchronizationManager ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) { conHolder.requested(); if (!conHolder.hasConnection()) { conHolder.setConnection(fetchConnection(dataSource)); } return conHolder.getConnection(); } /// .... }
TransactionSynchronizationManager.getResource(dataSource); -> org.springframework.transaction.support.TransactionSynchronizationManager#getResource @Nullable public static Object getResource(Object key) { // key Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key); // 获取值 Object value = doGetResource(actualKey); //... return value; }
doGetResource(actualKey); ->org.springframework.transaction.support.TransactionSynchronizationManager#doGetResource @Nullable private static Object doGetResource(Object actualKey) { // 获取map Map
数字化转型应重点构筑的核心能力解析数字化转型应重点构筑的几大核心能力1以客户为中心的组织能力体系1)组织结构从以产品为中心向以客户为中心转变传统模式下,零售企业以我为中心,不同产品的营销服务通常自成体系。数字经济下
激光雷达和视觉算法哪个更适合自动驾驶?自动驾驶注定会成为未来改变世界的技术不过在这个技术蓬勃发展的当下却有两个旗帜鲜明的技术流派一派支持只用视觉算法实现L4L5级自动驾驶另一派认为视觉算法安全冗余不够完全可靠的自动驾驶
AMD放大招R93950X不到六千眼看着2019年还剩不到两个月就要结束了,按理说今年的电脑处理器市场也该尘埃落定,但AMD方面似乎并不这么想。11月7日AMD方面正式公布了锐龙93950X(以下简称R93950X
情怀有点贵摩托罗拉折叠翻盖手机发布北京时间11月14日,摩托罗拉在洛杉矶发布了Razr2019系列折叠屏翻盖手机,这部手机从预热到正式发布可谓是赚足了眼球,毕竟把折叠屏手机做成翻盖样式看上去比三星以及华为的折叠屏手
二手备用手机水太深?明白这些不被坑随着社会发展越来越快,很多小伙伴平时都使用着不止一张卡,但除去主力手机外,备用机型基本就是接打个电话,花太多钱又不合适,毕竟钱也不是大风刮来的。于是很多小伙伴都把目光转向了二手手机
夹缝中的AMD,能凭借锐龙三代翻身吗?前段时间AMD发布了旗下最新的锐龙系列处理器,这一代锐龙处理器依然走高性价比路线,虽然三代锐龙处理器还没有正式发货,但却已经在民间激起了惊涛骇浪,因为这一代的锐龙处理器的性价比实在
密码管理应用程序Dashlane视觉形象升级Dashlane是一款移动和桌面应用程序,创办于2009年,用户可以通过该应用管理自己的互联网上的各种帐号和密码,自动填写登陆表单,实现简单安全的快捷登录。最近,他们公布了由Pen
公路客运运营商ALSA视觉形象升级ALSA创办于1923年,是西班牙公路客运领域的领先运营商,作为一个整体运营商,它能够满足市民的不同交通需求,提供广泛的区域国家国际城市长途汽车租赁和旅游服务。此外,还专门从事公交
败光120亿,坑了9000名员工,80后富二代是如何搞垮山西最大民企2003年1月22日上午,山西闻喜县前企业家冯引亮,带上了两把枪,决定亲自上门寻找李海仓,做最后的摊牌。自从冯引亮回来家乡之后,李海仓就一直避而不见。冯引亮想将自己纸厂的那块地,以
30岁,喜茶创始人身家150亿万千少女追捧的喜茶又又双叒叕融资了!近期,喜茶刚刚交割完毕新一轮5亿美元的融资,投资方包括黑蚁资本腾讯红杉资本高瓴资本淡马锡LCatterton和日初资本。而喜茶的估值在这一轮融资
佛媛生意坐禅抄经穿Dior,佛门炫富也能火?在冲浪第一线的你,不知道有没有发现,小红书抖音上的网红开始争当佛媛了。佛媛目前没有明确的含义,泛指以抄经拜佛品茶为日常的生活方式,同时具有美貌和财富的新名媛,是礼佛和名媛的结合体。