Foxnic-SQL (11) —— DAO 特性 : 事務管理

Foxnic-SQL (11) —— DAO 特性 : 事務管理

概述

事務管理是任何一個數(shù)據層工具所必須的,F(xiàn)oxnic-SQL 既然是基于 Spring JDBC 的自然默認就支持 @Transactional 注解,另外 Foxnic-SQL 的 DAO 對象還支持手動事務。

本文中的示例代碼均可在 https://gitee.com/LeeFJ/foxnic-samples 項目中找到。

手動事務

手動事務通過 DAO 對象的 beginTransaction() 方法、commit() 方法、rollback() 方法完成,下面是一個手動事務的例子:

public class DAO_ManualTransactionDemo {

? ? public static void main(String[] args) {

? ? ? ? demo1(true);

? ? ? ? demo1(false);

? ? }

? ? /**

* 1、查詢不分頁記錄集

* */

? ? public static void demo1(boolean exp) {

? ? ? ? // 通過 DBInstance 拿到 DAO 對象

? ? ? ? DAO dao=DBInstance.DEFAULT.dao();

? ? ? ? String id = null;

? ? ? ? try {

? ? ? ? ? ? // 啟動事務

? ? ? ? ? ? dao.beginTransaction();

? ? ? ? ? ? System.out.println("開始事務");

? ? ? ? ? ? // 插入數(shù)據

? ? ? ? ? ? id=insertAddress(dao,"13777-"+exp);

? ? ? ? ? ? if(exp) {

? ? ? ? ? ? ? ? throw new RuntimeException("模擬異常");

? ? ? ? ? ? }

? ? ? ? ? ? // 提交

? ? ? ? ? ? dao.commit();

? ? ? ? ? ? System.out.println("提交事務");

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? // 回滾

? ? ? ? ? ? dao.rollback();

? ? ? ? ? ? System.out.println("回滾事務");

? ? ? ? }

? ? ? ? Rcd address=queryAddress(dao,id);

? ? ? ? if(address==null) {

? ? ? ? ? ? System.out.println("數(shù)據未插入");

? ? ? ? } else {

? ? ? ? ? ? System.out.println("數(shù)據已插入");

? ? ? ? }

? ? }

? ? /**

* 插入數(shù)據

* */

? ? public static String insertAddress(DAO dao,String phone) {

? ? ? ? // 創(chuàng)建語句對象

? ? ? ? Insert insert=new Insert("example_address");

? ? ? ? String id= IDGenerator.getSnowflakeIdString();

? ? ? ? // 設置值

? ? ? ? insert.set("id",id)

? ? ? ? ? ? .set("name","leefj")

? ? ? ? ? ? // 如果是 null 則不連入SQL語句

? ? ? ? ? ? .setIf("phone_number",phone)

? ? ? ? ? ? .set("address","寧波")

? ? ? ? ? ? .set("region_type","國內")

? ? ? ? ? ? .set("create_time",new Date())

? ? ? ? ? ? // 設置數(shù)據庫表達式

? ? ? ? ? ? .setExpr("update_time","now()");

? ? ? ? // 輸出語句

? ? ? ? System.out.println(insert.getSQL());

? ? ? ? // 執(zhí)行語句

? ? ? ? Integer suc=dao.execute(insert);

? ? ? ? // 如果執(zhí)行成功,返回ID,否則返回 null

? ? ? ? if(suc==1) {

? ? ? ? ? ? return id;

? ? ? ? } else {

? ? ? ? ? ? return null;

? ? ? ? }

? ? }

? ? /**

* 查詢

* */

? ? public static Rcd queryAddress(DAO dao,String id) {

? ? ? ? // 創(chuàng)建語句對象

? ? ? ? Select select=new Select("example_address");

? ? ? ? // 設置值

? ? ? ? select.where().and("id=?",id);

? ? ? ? // 輸出語句

? ? ? ? System.out.println(select.getSQL());

? ? ? ? // 執(zhí)行語句

? ? ? ? Rcd address=dao.queryRecord(select);

? ? ? ? // 如果執(zhí)行成功,返回記錄對象,否則返回 null

? ? ? ? return address;

? ? }

}

自動事務

自動事務的前提是被注解 @Transactional 的對象需要是 Spring 容器管理的 Bean。所以自動事務通常會在 Web 應用中使用。自動事務需要首先定義數(shù)據源和事務管理器,并將兩者綁定,如下代碼所示:

@Configuration

? ? public class DatasourceConfig {

? ? ? ? public static final String PRIMARY_DATASOURCE_CONFIG_KEY = "spring.datasource.druid.primary";

? ? ? ? public static final String PRIMARY_DATA_SOURCE_NAME = "primaryDataSource";

? ? ? ? @Bean(name = PRIMARY_DATA_SOURCE_NAME)

? ? ? ? @ConfigurationProperties(PRIMARY_DATASOURCE_CONFIG_KEY)

? ? ? ? public DruidDataSource primaryDataSource() {

? ? ? ? ? ? return DruidDataSourceBuilder.create().build();

? ? ? ? }

? ? ? ? @Bean

? ? ? ? @Primary

? ? ? ? public DataSourceTransactionManager primaryTransactionManager(

? ? ? ? ? ? @Qualifier(PRIMARY_DATA_SOURCE_NAME) DataSource dataSource) {

? ? ? ? ? ? return new DataSourceTransactionManager(dataSource);

? ? ? ? }

? ? }

@Transactional注解

如果需要更高級的事務控制,則使用@Transactional注解,@Transactional 注解雖然方便地實現(xiàn)事務托管,但是還是有很多地方需要注意的,下面我們來了解一下在使用@Transactional注解時需要注意的點。

1、多數(shù)據源時需指定事務管理器名稱;

2、Spring事務是通過ThreadLocal類來實現(xiàn),所以只有主線程有事務管理,一個線程一個事務。

3、@Transactiona 注解需要事務管理器支持,若無事務管理器支持,則不生效。

4、@Transactional 注解可用于接口定義、接口方法、類定義、類public方法四個位置,非public方法事務不生效。

5、Spring事務控制是基于AOP的,請明確代理類型。proxy-target-class=true時,使用cglib的基于類的代理;proxy-target-class=false時,使用JDK的基于接口的代理。基于上述情況,@Transactional 注解建議放到類定義或類方法上。

6、如果類定義中無 @Transactional 注解,它的方法A無 @Transactional 注解,但方法B有 @Transactional 注解,此時若在同一個類中,由A調用B,則B上的事務無效。如果類定義中有@Transactional注解,則它的方法,無論有無 @Transactional 注解,事務均有效??傊?,如果要使事務有效,調用時進入類的第一個類方法必須有 @Transactional 注解。

7、Spring 使用聲明式事務處理,默認情況下, 如果被注解的數(shù)據庫操作方法中發(fā)生了 unchecked 異常(編譯器不檢查的異常,如 RuntimeException),所有的數(shù)據庫操作將 rollback;如果發(fā)生的異常是 checked 異常(編譯器檢查,需要用try cathch 捕獲處理的異常,如 Exception),默認情況下數(shù) 據庫操作還是會提交的。當然也可在 @Transactional 注解中指定回滾的異常類型。

下面是使用 @Transactional? 事務托管的幾個示例:

@Transactional(AppDAO.TRANSACTION_MANAGER)

public String te1(String act) throws Exception

{

if(act==null) act="none";

dao.execute("update trans set name=?? where code='119'",act+":"+System.currentTimeMillis());

if(act.equals("checked")) {

//事務不回滾

throw new Exception("異常");

}

if(act.equals("unchecked")) {

//事務回滾

throw new RuntimeException("異常");

}

return "OK";

}

變更默認的回滾異常,指定回滾或不回滾的異常類型:

@Transactional(transactionManager=AppDAO.TRANSACTION_MANAGER,rollbackFor= {Exception.class},noRollbackFor= {RuntimeException.class})

public String te2(String act) throws Exception

{

if(act==null) act="none";

dao.execute("update trans set name=?? where code='119'",act+":"+System.currentTimeMillis());

if(act.equals("checked")) {

//事務回滾

throw new Exception("異常");

}

if(act.equals("unchecked")) {

//事務不回滾

throw new RuntimeException("異常");

}

return "OK";

}

事務傳播

Spring 的事務的傳播行為,默認值為 Propagation.REQUIRED。 可選的值有:

1、Propagation.REQUIRED:如果當前存在事務,則加入該事務,如果當前不存在事務,則創(chuàng)建一個新的事務。

2、Propagation.SUPPORTS:如果當前存在事務,則加入該事務;如果當前不存在事務,則以非事務的方式繼續(xù)運行。

3、Propagation.MANDATORY:如果當前存在事務,則加入該事務;如果當前不存在事務,則拋出異常。

4、Propagation.REQUIRES_NEW:重新創(chuàng)建一個新的事務,如果當前存在事務,暫停當前的事務。

5、Propagation.NOT_SUPPORTED:以非事務的方式運行,如果當前存在事務,暫停當前的事務。

6、Propagation.NEVER:以非事務的方式運行,如果當前存在事務,則拋出異常。

7、Propagation.NESTED:和 Propagation.REQUIRED 效果一樣。

事務隔離

isolation 屬性,事務的隔離級別,默認值為 Isolation.DEFAULT??蛇x的值有:

1、Isolation.DEFAULT:使用底層數(shù)據庫默認的隔離級別。MYSQL:默認為 REPEATABLE_READ 級別;SQLSERVER:默認為 READ_COMMITTED 級別;Oracle:默認為 READ_COMMITTED 級別。

2、Isolation.READ_UNCOMMITTED

3、Isolation.READ_COMMITTED

4、Isolation.REPEATABLE_READ

5、Isolation.SERIALIZABLE

其它參數(shù)

1、timeout 屬性:事務的超時時間,默認值為-1。如果超過該時間限制但事務還沒有完成,則自動回滾事務。

2、readOnly 屬性:指定事務是否為只讀事務,默認值為 false;為了忽略那些不需要事務的方法,比如讀取數(shù)據,可以設置 read-only 為 true。

小結

本節(jié)主要介紹了在 Foxni-SQL 中的事務管理,包括了手動事務個 Spring 托管的自動事務。在使用自動事務時要注意本文中提到的針對? @Transactional 注解使用的注意事項。

相關項目

https://gitee.com/LeeFJ/foxnic

https://gitee.com/LeeFJ/foxnic-web

https://gitee.com/lank/eam

https://gitee.com/LeeFJ/foxnic-samples

官方文檔

http://foxnicweb.com/docs/doc.html

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容