精品熟女碰碰人人a久久,多姿,欧美欧美a v日韩中文字幕,日本福利片秋霞国产午夜,欧美成人禁片在线观看

一文解析spring中事務的傳播機制

一文解析spring中事務的傳播機制

本文講解"一文解析spring中事務的傳播機制",希望能夠解決相關問題。

 

spring中的事務

spring的事務其實就是數據庫的事務操作,符合acid標準,也具有標準的事務隔離級別。

spring中的事務只是對jdbc事務進行一些封裝與擴展,其底層最終還是會使用到jdbc的這套api。但是spring事務有自己的特點,也就是事務傳播機制。

所謂事務傳播機制,也就是在事務在多個方法的調用中是如何傳遞的,是重新創建事務還是使用父方法的事務?父方法的回滾對子方法的事務是否有影響?這些都是可以通過事務傳播機制來決定的。

準備工作

實體類

area

package com.morris.spring.entity;import lombok.data;import java.io.serializable;@datapublic class area implements serializable {private integer id;private string areaname;private integer areacode;}

good

package com.morris.spring.entity;import lombok.data;import java.io.serializable;import java.math.bigdecimal;@datapublic class good implements serializable {private integer id;private string goodname;private bigdecimal price;}

dao層

areadao

package com.morris.spring.dao;import com.morris.spring.entity.area;import org.springframework.beans.factory.annotation.autowired;import org.springframework.jdbc.core.jdbctemplate;public class areadao {@autowiredprivate jdbctemplate jdbctemplate;public boolean insert(area area) {string sql = "insert into t_area(area_name, area_code) values(?,?)";return jdbctemplate.update(sql, area.getareaname(), area.getareacode()) > 0;}}

gooddao

package com.morris.spring.dao;import com.morris.spring.entity.good;import org.springframework.beans.factory.annotation.autowired;import org.springframework.jdbc.core.jdbctemplate;public class gooddao {@autowiredprivate jdbctemplate jdbctemplate;public boolean insert(good good) {string sql = "insert into t_good(good_name, price) values(?,?)";return jdbctemplate.update(sql, good.getgoodname(), good.getprice()) > 0;}}

service層

areaserviceimpl

package com.morris.spring.service;import com.morris.spring.dao.areadao;import com.morris.spring.entity.area;import org.springframework.beans.factory.annotation.autowired;import org.springframework.transaction.annotation.propagation;import org.springframework.transaction.annotation.transactional;public class areaserviceimpl implements areaservice {@autowiredprivate areadao areadao;@transactional(propagation = propagation.required)@overridepublic boolean addarea(int i) {int y = 1000000 / i;area area = new area();area.setareacode(y);area.setareaname("shenzhen");return areadao.insert(area);}}

goodserviceimpl

package com.morris.spring.service;import com.morris.spring.dao.gooddao;import com.morris.spring.entity.good;import org.springframework.beans.factory.annotation.autowired;import org.springframework.transaction.annotation.propagation;import org.springframework.transaction.annotation.transactional;import java.math.bigdecimal;public class goodserviceimpl implements goodservice {@autowiredprivate gooddao gooddao;@transactional(propagation = propagation.required)@overridepublic boolean addgood() {good good = new good();good.setgoodname("iphone");good.setprice(bigdecimal.valueof(99999));return gooddao.insert(good);}}

transactionservice

package com.morris.spring.service;import org.springframework.beans.factory.annotation.autowired;import org.springframework.stereotype.component;import org.springframework.transaction.annotation.propagation;import org.springframework.transaction.annotation.transactional;@componentpublic class transactionservice {@autowiredprivate goodservice goodservice;@autowiredprivate areaservice areaservice;@transactional(propagation = propagation.required)public void addgoodandarea() {system.out.println("------addgoodandarea-------");areaservice.addarea(10);goodservice.addgood();}}
測試類

transactionpropagationdemo

package com.morris.spring.demo.jdbc;import com.morris.spring.config.jdbcconfig;import com.morris.spring.dao.areadao;import com.morris.spring.dao.gooddao;import com.morris.spring.service.areaserviceimpl;import com.morris.spring.service.goodserviceimpl;import com.morris.spring.service.transactionservice;import org.junit.jupiter.api.test;import org.springframework.context.annotation.annotationconfigapplicationcontext;/** * 事務的傳播機制 */public class transactionpropagationdemo {@testpublic void test() {annotationconfigapplicationcontext applicationcontext = new annotationconfigapplicationcontext();applicationcontext.register(gooddao.class);applicationcontext.register(areadao.class);applicationcontext.register(goodserviceimpl.class);applicationcontext.register(areaserviceimpl.class);applicationcontext.register(jdbcconfig.class);applicationcontext.register(transactionservice.class);applicationcontext.refresh();transactionservice transactionservice = applicationcontext.getbean(transactionservice.class);transactionservice.addgoodandarea();}}

傳播機制

具體選項可以參考枚舉類org.springframework.transaction.annotation.propagation。

選項 說明
required 默認選項。如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。
supports 支持當前事務,如果當前沒有事務,就以非事務方式執行。
mandatory 使用當前的事務,如果當前沒有事務,就拋出異常。
requires_new 新建事務,如果當前存在事務,把當前事務掛起。
not_supported 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
never 以非事務方式執行,如果當前存在事務,則拋出異常。
nested 如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與required類似的操作。
required

默認選項。如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。

配置如下:

  • transactionservice:required

  • areaserviceimpl:required

  • goodserviceimpl:required

運行上面的demo,運行結果如下:

// 創建第一個事務
debug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.transactionservice.addgoodandarea]: propagation_required,isolation_default
// 創建第一個連接
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@8ef162] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] to manual commit
------addgoodandarea-------																				   
// 在第一個事務中執行
debug datasourcetransactionmanager:487 - participating in existing transaction
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]
// 在第一個事務中執行
debug datasourcetransactionmanager:487 - participating in existing transaction
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_area(area_name, area_code) values(?,?)]
// 提交第一個事務
debug datasourcetransactionmanager:763 - initiating transaction commit
debug datasourcetransactionmanager:329 - committing jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@8ef162]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] after transaction

總結:

  • 當外層沒有事務的時候,transactionservice.addgoodandarea()方法執行發現沒有事務可用,自己新建事務。

  • goodservice.addgood()和areaservice.addarea()執行時發現已有事務,就使用當前事務執行。

requires_new

新建事務,如果當前存在事務,把當前事務掛起。

配置如下:

  • transactionservice:required

  • goodserviceimpl:requires

  • areaserviceimpl:requires_new

運行結果如下:

// 創建第一個事務
debug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.transactionservice.addgoodandarea]: propagation_required,isolation_default
// 創建第一個連接
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@f9aa66] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@f9aa66] to manual commit
------addgoodandarea-------																			   
// 掛起第一個事務并創建第二個事務
debug datasourcetransactionmanager:446 - suspending current transaction, creating new transaction with name [com.morris.spring.service.areaserviceimpl.addarea]
// 創建第二個連接
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@116fc68] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@116fc68] to manual commit
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_area(area_name, area_code) values(?,?)]
// 提交第二個事務
debug datasourcetransactionmanager:763 - initiating transaction commit
debug datasourcetransactionmanager:329 - committing jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@116fc68]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@116fc68] after transaction
// 恢復第一個事務
debug datasourcetransactionmanager:1043 - resuming suspended transaction after completion of inner transaction
// 在第一個事務中執行
debug datasourcetransactionmanager:487 - participating in existing transaction
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]
debug datasourcetransactionmanager:763 - initiating transaction commit
debug datasourcetransactionmanager:329 - committing jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@f9aa66]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@f9aa66] after transaction

總結:areaserviceimpl.addarea()執行時發現已有事務,就把當前事務掛起,執行完后再恢復。

supports

支持當前事務,如果當前沒有事務,就以非事務方式執行。

配置如下:

  • transactionservice:supports

  • areaserviceimpl:required

  • goodserviceimpl:supports

運行結果如下:

// transactionservice.addgoodandarea以非事務方式運行
------addgoodandarea-------
// 開啟第一個事務
debug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.areaserviceimpl.addarea]: propagation_required,isolation_default
// 創建第一個連接
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@1691f3d] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@1691f3d] to manual commit
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_area(area_name, area_code) values(?,?)]
// 提交第一個事務
debug datasourcetransactionmanager:763 - initiating transaction commit
debug datasourcetransactionmanager:329 - committing jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@1691f3d]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@1691f3d] after transaction
debug datasourcetransactionmanager:1043 - resuming suspended transaction after completion of inner transaction
// areaserviceimpl.addarea以非事務方式運行
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]

總結:當前沒有事務,transactionservice.addgoodandarea()和areaserviceimpl.addarea()以非事務方式運行。

修改配置如下:

  • transactionservice:required

  • areaserviceimpl:supports

  • goodserviceimpl:supports

運行結果如下:

// 開啟第一個事務
debug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.transactionservice.addgoodandarea]: propagation_required,isolation_default
// 創建第一個連接
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@11158fb] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@11158fb] to manual commit
------addgoodandarea-------																		  
// 在第一個事務中執行
debug datasourcetransactionmanager:487 - participating in existing transaction
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_area(area_name, area_code) values(?,?)]
// 在第一個事務中執行
debug datasourcetransactionmanager:487 - participating in existing transaction
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]
// 提交第一個事務
debug datasourcetransactionmanager:763 - initiating transaction commit
debug datasourcetransactionmanager:329 - committing jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@11158fb]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@11158fb] after transaction

總結:當前有事務,goodserviceimpl.addgood()和areaserviceimpl.addarea()以事務方式運行。

mandatory

使用當前的事務,如果當前沒有事務,就拋出異常。

配置如下:

  • transactionservice:required

  • areaserviceimpl:required

  • goodserviceimpl:mandatory

運行結果如下:

// 創建第一個事務
ebug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.transactionservice.addgoodandarea]: propagation_required,isolation_default
// 創建第一個連接
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@11c4a3f] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@11c4a3f] to manual commit
------addgoodandarea-------																  
// 在第一個事務中執行
debug datasourcetransactionmanager:487 - participating in existing transaction
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_area(area_name, area_code) values(?,?)]
// 在第一個事務中執行
debug datasourcetransactionmanager:487 - participating in existing transaction
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]
// 提交第一個事務
debug datasourcetransactionmanager:763 - initiating transaction commit
debug datasourcetransactionmanager:329 - committing jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@11c4a3f]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@11c4a3f] after transaction

總結:當前有事務,goodserviceimpl.addgood()以事務方式運行。

修改配置如下:

  • transactionservice:supports

  • areaserviceimpl:mandatory

  • goodserviceimpl:supports

運行結果如下:

------addgoodandarea-------
debug datasourcetransactionmanager:888 - should roll back transaction but cannot - no transaction available
org.springframework.transaction.illegaltransactionstateexception: no existing transaction found for transaction marked with propagation 'mandatory'
	at org.springframework.transaction.support.abstractplatformtransactionmanager.gettransaction(abstractplatformtransactionmanager.java:372)
	at org.springframework.transaction.interceptor.transactionaspectsupport.createtransactionifnecessary(transactionaspectsupport.java:595)
	at org.springframework.transaction.interceptor.transactionaspectsupport.invokewithintransaction(transactionaspectsupport.java:374)
	at org.springframework.transaction.interceptor.transactioninterceptor.invoke(transactioninterceptor.java:118)
	at org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:205)
	at org.springframework.aop.framework.jdkdynamicaopproxy.invoke(jdkdynamicaopproxy.java:219)
	at com.sun.proxy.$proxy23.addarea(unknown source)
	at com.morris.spring.service.transactionservice.addgoodandarea(transactionservice.java:20)

總結:當前沒有有事務,areaserviceimpl.addarea()會拋出異常。

not_supported

以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

配置如下:

  • transactionservice:required

  • areaserviceimpl:not_supported

  • goodserviceimpl:not_supported

運行結果如下:

// 開啟第一個事務
debug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.transactionservice.addgoodandarea]: propagation_required,isolation_default
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@8ef162] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] to manual commit
------addgoodandarea-------
// 掛起第一個事務
debug datasourcetransactionmanager:436 - suspending current transaction
// 以非事務方式運行
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_area(area_name, area_code) values(?,?)]
debug datasourceutils:115 - fetching jdbc connection from datasource
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
// 恢復第一個事務
debug datasourcetransactionmanager:1043 - resuming suspended transaction after completion of inner transaction
// 掛起第一個事務
debug datasourcetransactionmanager:436 - suspending current transaction
// 以非事務方式運行
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]
debug datasourceutils:115 - fetching jdbc connection from datasource
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
// 恢復第一個事務
debug datasourcetransactionmanager:1043 - resuming suspended transaction after completion of inner transaction
// 提交第一個事務
debug datasourcetransactionmanager:763 - initiating transaction commit
debug datasourcetransactionmanager:329 - committing jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@8ef162]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] after transaction

總結:執行goodserviceimpl.addgood()和areaserviceimpl.addarea()時當前存在事務,就把當前事務掛起。

never

以非事務方式執行,如果當前存在事務,則拋出異常。

配置如下:

  • transactionservice:never

  • areaserviceimpl:never

  • goodserviceimpl:never

運行結果如下:

// 沒有事務都以非事務方式運行
------addgoodandarea-------
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_area(area_name, area_code) values(?,?)]
debug datasourceutils:115 - fetching jdbc connection from datasource
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]

總結:當前沒有事務都以非事務方式執行。

修改配置如下:

  • transactionservice:required

  • areaserviceimpl:never

  • goodserviceimpl:never

運行結果如下:

// 開啟第一個事務
debug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.transactionservice.addgoodandarea]: propagation_required,isolation_default
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@8ef162] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] to manual commit
------addgoodandarea-------
debug datasourcetransactionmanager:864 - initiating transaction rollback
debug datasourcetransactionmanager:345 - rolling back jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@8ef162]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] after transaction
org.springframework.transaction.illegaltransactionstateexception: existing transaction found for transaction marked with propagation 'never'
	at org.springframework.transaction.support.abstractplatformtransactionmanager.handleexistingtransaction(abstractplatformtransactionmanager.java:430)
	at org.springframework.transaction.support.abstractplatformtransactionmanager.gettransaction(abstractplatformtransactionmanager.java:362)
	at org.springframework.transaction.interceptor.transactionaspectsupport.createtransactionifnecessary(transactionaspectsupport.java:595)
	at org.springframework.transaction.interceptor.transactionaspectsupport.invokewithintransaction(transactionaspectsupport.java:374)
	at org.springframework.transaction.interceptor.transactioninterceptor.invoke(transactioninterceptor.java:118)
	at org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:205)
	at org.springframework.aop.framework.jdkdynamicaopproxy.invoke(jdkdynamicaopproxy.java:219)
	at com.sun.proxy.$proxy23.addarea(unknown source)
	at com.morris.spring.service.transactionservice.addgoodandarea(transactionservice.java:20)

總結:areaserviceimpl.addarea()執行時存在事務就會拋出異常。

nested

如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與required類似的操作。

配置如下:

  • transactionservice:required

  • goodserviceimpl:nested

  • areaserviceimpl:nested

運行結果如下:

// 創建第一個事務
ebug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.transactionservice.addgoodandarea]: propagation_required,isolation_default
// 創建第一個連接
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@8ef162] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] to manual commit
------addgoodandarea-------
// 創建回滾點
debug datasourcetransactionmanager:466 - creating nested transaction with name [com.morris.spring.service.areaserviceimpl.addarea]
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_area(area_name, area_code) values(?,?)]
// 釋放回滾點
debug datasourcetransactionmanager:754 - releasing transaction savepoint
// 創建回滾點
debug datasourcetransactionmanager:466 - creating nested transaction with name [com.morris.spring.service.goodserviceimpl.addgood]
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]
// 釋放回滾點
debug datasourcetransactionmanager:754 - releasing transaction savepoint
debug datasourcetransactionmanager:763 - initiating transaction commit
debug datasourcetransactionmanager:329 - committing jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@8ef162]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] after transaction

如果不拋出異常,使用required與nested都差不多,區別在于發生異常,下面演示required與nested發生異常時的區別:

配置如下:

  • transactionservice:required

  • areaserviceimpl:required

  • goodserviceimpl:required

transactionservice.addgoodandarea修改如下:

@transactional(propagation = propagation.required)
public void addgoodandarea() {
	system.out.println("------addgoodandarea-------");
	try {
		areaservice.addarea(0);
	} catch (exception e) {
		e.printstacktrace();
	}
	goodservice.addgood();
}

運行結果如下:

debug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.transactionservice.addgoodandarea]: propagation_required,isolation_default
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@f9aa66] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@f9aa66] to manual commit
------addgoodandarea-------
debug datasourcetransactionmanager:487 - participating in existing transaction
debug datasourcetransactionmanager:877 - participating transaction failed - marking existing transaction as rollback-only
debug datasourcetransactionmanager:360 - setting jdbc transaction [com.mysql.cj.jdbc.connectionimpl@f9aa66] rollback-only
java.lang.arithmeticexception: / by zero
	at com.morris.spring.service.areaserviceimpl.addarea(areaserviceimpl.java:18)
... ...
debug datasourcetransactionmanager:487 - participating in existing transaction
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]
debug datasourcetransactionmanager:723 - global transaction is marked as rollback-only but transactional code requested commit
debug datasourcetransactionmanager:877 - participating transaction failed - marking existing transaction as rollback-only
debug datasourcetransactionmanager:360 - setting jdbc transaction [com.mysql.cj.jdbc.connectionimpl@f9aa66] rollback-only
debug datasourcetransactionmanager:723 - global transaction is marked as rollback-only but transactional code requested commit
debug datasourcetransactionmanager:864 - initiating transaction rollback
debug datasourcetransactionmanager:345 - rolling back jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@f9aa66]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@f9aa66] after transaction
org.springframework.transaction.unexpectedrollbackexception: transaction rolled back because it has been marked as rollback-only
	at org.springframework.transaction.support.abstractplatformtransactionmanager.processrollback(abstractplatformtransactionmanager.java:905)
... ...

從運行結果可以發現事務全部都回滾了。

將上面的配置修改如下:

  • transactionservice:required

  • areaserviceimpl:nested

  • goodserviceimpl:nested

運行結果如下:

debug datasourcetransactionmanager:381 - creating new transaction with name [com.morris.spring.service.transactionservice.addgoodandarea]: propagation_required,isolation_default
debug drivermanagerdatasource:144 - creating new jdbc drivermanager connection to [jdbc:mysql://127.0.0.1:3306/test?useunicode=true&allowmultiqueries=true&characterencoding=utf-8&usefastdateparsing=false&zerodatetimebehavior=converttonull]
debug datasourcetransactionmanager:265 - acquired connection [com.mysql.cj.jdbc.connectionimpl@8ef162] for jdbc transaction
debug datasourcetransactionmanager:283 - switching jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] to manual commit
------addgoodandarea-------
debug datasourcetransactionmanager:466 - creating nested transaction with name [com.morris.spring.service.areaserviceimpl.addarea]
debug datasourcetransactionmanager:857 - rolling back transaction to savepoint
java.lang.arithmeticexception: / by zero
	at com.morris.spring.service.areaserviceimpl.addarea(areaserviceimpl.java:18)
... ...
debug datasourcetransactionmanager:466 - creating nested transaction with name [com.morris.spring.service.goodserviceimpl.addgood]
debug jdbctemplate:860 - executing prepared sql update
debug jdbctemplate:609 - executing prepared sql statement [insert into t_good(good_name, price) values(?,?)]
debug datasourcetransactionmanager:754 - releasing transaction savepoint
debug datasourcetransactionmanager:763 - initiating transaction commit
debug datasourcetransactionmanager:329 - committing jdbc transaction on connection [com.mysql.cj.jdbc.connectionimpl@8ef162]
debug datasourcetransactionmanager:390 - releasing jdbc connection [com.mysql.cj.jdbc.connectionimpl@8ef162] after transaction

從運行結果可以發現areaservice.addarea()回滾了(本來就沒有提交內容),goodservice.addgood()的內容提交了。

注意只有運行時異常以及rollbakcfor指定的異常才會回滾。

相關文章