<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
1.Spring事務底層是基於資料庫事務和AOP機制的
2.首先對於使用了@Transactional註解的Bean,Spring會建立一個代理物件作為Bean
3.當呼叫代理物件的方法時,會先判斷該方法上是否加了@Transactional註解
4.如果加了,那麼則利用事務管理器建立一個資料庫連線
5.並且修改資料庫連線的autocommit屬性為false,禁止此連線的自動提交,這是實現Spring事務非常重要的一步
6.然後執行當前方法,方法中會執行sql
7.執行完當前方法後,如果沒有出現異常就直接提交事務
8.如果出現了異常,並且這個異常是需要回滾的就會回滾事務,否則仍然提交事務
注:
1.Spring事務的隔離級別對應的就是資料庫的隔離級別
2.Spring事務的傳播機制是Spring事務自己實現的,也是Spring事務中最複雜的
3.Spring事務的傳播機制是基於資料庫連線來做的,一個資料庫連線就是一個事務,如果傳播機制設定為需要新開一個事務,那麼實際上就是先新建一個資料庫連線,在此新資料庫連線上執行sql
事務幾種實現方式
(1)程式設計式事務管理對基於 POJO 的應用來說是唯一選擇。我們需要在程式碼中呼叫beginTransaction()、commit()、rollback()等事務管理相關的方法,這就是程式設計式事務管理。
(2)基於 TransactionProxyFactoryBean的宣告式事務管理
(3)基於 @Transactional 的宣告式事務管理
(4)基於Aspectj AOP設定事務
1、transactionTemplate
此種方式是自動的事務管理,無需手動開啟、提交、回滾。
設定事務管理器
<!-- 設定事務管理器 ,封裝了所有的事務操作,依賴於連線池 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
設定事務模板物件
<!-- 設定事務模板物件 --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"></property> </bean>
測試
@Controller @RequestMapping("/tx") @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:applicationContext.xml"}) public class TransactionController { @Resource public TransactionTemplate transactionTemplate; @Resource public DataSource dataSource; private static JdbcTemplate jdbcTemplate; private static final String INSERT_SQL = "insert into cc(id) values(?)"; private static final String COUNT_SQL = "select count(*) from cc"; @Test public void TransactionTemplateTest(){ //獲取jdbc核心類物件,進而運算元據庫 jdbcTemplate = new JdbcTemplate(dataSource); //通過註解 獲取xml中設定的 事務模板物件 transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); //重寫execute方法實現事務管理 transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { jdbcTemplate.update(INSERT_SQL, "33"); //欄位sd為int型,所以插入肯定失敗報異常,自動回滾,代表TransactionTemplate自動管理事務 } }); int i = jdbcTemplate.queryForInt(COUNT_SQL); System.out.println("表中記錄總數:"+i); } }
2、PlatformTransactionManager
使用 事務管理器 PlatformTransactionManager 物件,PlatformTransactionManager是DataSourceTransactionManager實現的介面類
此方式,可手動開啟、提交、回滾事務。
只需要:設定事務管理
<!-- 設定事務管理 ,封裝了所有的事務操作,依賴於連線池 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
測試
@Controller @RequestMapping("/tx") @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:applicationContext.xml"}) public class TransactionController { @Resource public PlatformTransactionManager transactionManager;//這裡就是將設定資料管理物件注入進來, @Resource public DataSource dataSource; private static JdbcTemplate jdbcTemplate; private static final String INSERT_SQL = "insert into cc(id) values(?)"; private static final String COUNT_SQL = "select count(*) from cc"; @Test public void showTransaction(){ //定義使用隔離級別,傳播行為 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); //事務狀態類,通過PlatformTransactionManager的getTransaction方法根據事務定義獲取;獲取事務狀態後,Spring根據傳播行為來決定如何開啟事務 TransactionStatus transaction = transactionManager.getTransaction(def); jdbcTemplate = new JdbcTemplate(dataSource); int i = jdbcTemplate.queryForInt(COUNT_SQL); System.out.println("表中記錄總數:"+i); try { jdbcTemplate.update(INSERT_SQL,"2"); jdbcTemplate.update(INSERT_SQL,"是否");//出現異常,因為欄位為int型別,會報異常,自動回滾 transactionManager.commit(transaction); }catch (Exception e){ e.printStackTrace(); transactionManager.rollback(transaction); } int i1 = jdbcTemplate.queryForInt(COUNT_SQL); System.out.println("表中記錄總數:"+i1); } }
1、基於Aspectj AOP開啟事務
設定事務通知
<!-- 設定事務增強 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" /> </tx:attributes> </tx:advice>
設定織入
<!-- aop代理事務。掃描 cn.sys.service 路徑下所有的方法 --> <aop:config> <!-- 掃描 cn.sys.service 路徑下所有的方法,並加入事務處理 --> <aop:pointcut id="tx" expression="execution(* cn.sys.service.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="tx" /> </aop:config>
一個完整的例子
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> <!-- 建立載入外部Properties檔案物件 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:dataBase.properties"></property> </bean> <!-- 引入redis屬性組態檔 --> <import resource="classpath:redis-context.xml"/> <!-- 設定資料庫連線資源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" scope="singleton"> <property name="driverClassName" value="${driver}"></property> <property name="url" value="${url}"></property> <property name="username" value="${username}"></property> <property name="password" value="${password}"></property> <property name="maxActive" value="${maxActive}"></property> <property name="maxIdle" value="${maxIdle}"></property> <property name="minIdle" value="${minIdle}"></property> <property name="initialSize" value="${initialSize}"></property> <property name="maxWait" value="${maxWait}"></property> <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}"></property> <property name="removeAbandoned" value="${removeAbandoned}"></property> <!-- 設定sql心跳包 --> <property name= "testWhileIdle" value="true"/> <property name= "testOnBorrow" value="false"/> <property name= "testOnReturn" value="false"/> <property name= "validationQuery" value="select 1"/> <property name= "timeBetweenEvictionRunsMillis" value="60000"/> <property name= "numTestsPerEvictionRun" value="${maxActive}"/> </bean> <!--建立SQLSessionFactory物件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:MyBatis_config.xml"></property> </bean> <!-- 建立MapperScannerConfigurer物件 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.sys.dao"></property> </bean> <!-- 設定掃描器 IOC 註解 --> <context:component-scan base-package="cn.sys" /> <!-- 設定事務管理 ,封裝了所有的事務操作,依賴於連線池 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 設定事務模板物件 --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"></property> </bean> <!-- 設定事務增強 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" /> </tx:attributes> </tx:advice> <!-- aop代理事務 --> <aop:config> <aop:pointcut id="tx" expression="execution(* cn.sys.service.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="tx" /> </aop:config> </beans>
這樣就算是給 cn.sys.service下所有的方法加入了事務
也可以用springboot的設定類方式:
package com.junjie.test; @Configurationpublic class TxAnoConfig { /*事務攔截型別*/ @Bean("txSource") public TransactionAttributeSource transactionAttributeSource() { NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource(); /*唯讀事務,不做更新操作*/ RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, Collections.singletonList(new RollbackRuleAttribute(Exception.class))); requiredTx.setTimeout(60); Map<String, TransactionAttribute> txMap = new HashMap<>(); txMap.put("*", requiredTx); source.setNameMap(txMap); return source; } /** * 切面攔截規則 引數會自動從容器中注入 */ @Bean public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor) { AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor(); pointcutAdvisor.setAdvice(txInterceptor); pointcutAdvisor.setExpression("execution (* com.cmb..*Controller.*(..))"); return pointcutAdvisor; } /*事務攔截器*/ @Bean("txInterceptor") TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx) { return new TransactionInterceptor(tx, transactionAttributeSource()); } }
2、基於註解的 @Transactional 的宣告式事務管理
@Transactional public int saveRwHist(List list) { return rwDao.saveRwHist(list); }
這個註解的開啟需要在spring.xml里加上一個開啟註解事務的設定
以上的開啟事務方式,僅需要了解即可,如今在工作中,一般不會用到這幾種方式,過於繁瑣。一般都是直接用springboot自帶的@Transactional 註解,就可以完成這些事務管理操作。但是如果想知道事務底層的實現原理,以上的幾種原始方式,還是可以參考的。
這些僅為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45