1. 程式人生 > >中介軟體不支援setautocommit(false)怎麼辦?

中介軟體不支援setautocommit(false)怎麼辦?

前提

最近在某個公司實習,框架使用的是springmvc+spring+mybatis,具體名字就不說了,所有事務都沒有用無法回滾,導師叫我和db人員對接,我就寫了一個Jdbc的原生的測試測試程式碼如下:

 try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //url寫測試中介軟體的,這裡我替換了
        String url="jdbc:mysql://localhost:3306/taotao?characterEncoding=utf-8"
; String username="root"; String passwd="123456"; Connection conn= null; try { conn = DriverManager.getConnection(url, username, passwd); } catch (SQLException e) { e.printStackTrace(); } try{ conn.setAutoCommit(false);
PreparedStatement pstmt = conn.prepareStatement("insert into lztt (text) VALUES (?)") ; pstmt.execute("start TRANSACTION "); pstmt.setString(1,"memeda"); pstmt.executeUpdate(); PreparedStatement pstmt1 = conn.prepareStatement("insert into lztt (text) VALUES (?)"
) ; pstmt1.setString(1,"dsajdijsaoidjiosajdoisajdoijsaoidjsaoijdoisajidjsoajdijsaidjsajdsad"); pstmt1.executeUpdate(); conn.commit(); }catch (Exception e){ try { System.out.println(1); conn.rollback(); System.out.println(2); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { try { conn.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); } }

通過上面的程式碼發現,是setautocommit(flase)不起作用,不起作用咋辦,難道事務就這樣沒辦法回滾了嗎,這裡我們可以手動的使用pstmt來開啟事務這樣就可以了pstmt.execute(“start TRANSACTION “);這是我們原生的使用方法,但是非原生的使用怎麼辦,也就是我們使用框架mybatis和spring。接下來介紹我的思路:

思路一

修改Spring的事務管理器,看過Spring原始碼的朋友都知道DataSourceTransactionManager是我們管理Spring和Mybatis事務的地方,doBegin()方法就是我們建立事務的地方,doBegin方法程式碼如下:

@Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        Connection con = null;

        try {
            if (txObject.getConnectionHolder() == null ||
                    txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                Connection newCon = this.dataSource.getConnection();
                if (logger.isDebugEnabled()) {
                    logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
                }
                txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
            }

            txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
            con = txObject.getConnectionHolder().getConnection();

            Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
            txObject.setPreviousIsolationLevel(previousIsolationLevel);

            // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
            // so we don't want to do it unnecessarily (for example if we've explicitly
            // configured the connection pool to set it already).
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (logger.isDebugEnabled()) {
                    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }
                con.setAutoCommit(false);
            }
            txObject.getConnectionHolder().setTransactionActive(true);

            int timeout = determineTimeout(definition);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            }

            // Bind the session holder to the thread.
            if (txObject.isNewConnectionHolder()) {
                TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
            }
        }

        catch (Throwable ex) {
            DataSourceUtils.releaseConnection(con, this.dataSource);
            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
        }
    }

這裡有一句話:con.setAutoCommit(false);但是對我們的中介軟體不起作用,這時我的思路來了,繼承這個類然後重寫doBegin()方法,然而我發現這是不可能的,有些物件的方法是protected我子類根本沒辦法使用,這裡我放棄了。

思路二

所有程式碼重寫,這工作量太大,考慮了一會就沒想了

思路三

這也是我後面採取的思路,利用自定義註解加AOP的方法實現。我們可以利用AOP在方法執行之前就可以執行資料庫的東西,這下問題來了,我怎麼才能獲得資料庫連線了,看spring原始碼找了好久,找到了一個工具,利用資料庫連線池可以獲得繫結我們執行緒的連結。Connection connection = DataSourceUtils.getConnection(this.dataSource);
具體的切面:


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * Created by lz on 2016/7/11.
 */
@Component
@Aspect
public class TransactionBeforeAop {
    private static final Logger log = LoggerFactory.getLogger(TransactionBeforeAop.class);
    @Autowired
    private DataSource dataSource;
    @Before("@annotation(com.bank.TransactionBefore)")
    public void before(JoinPoint joinPoint){
        Connection connection = DataSourceUtils.getConnection(this.dataSource);

        try {
            connection.prepareStatement("").execute("start TRANSACTION");
        } catch (SQLException e) {
            log.error("occur Exception",e.getMessage());
        }
    }
}

註解定義如下:


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by lz on 2016/7/11.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface TransactionBefore {

}

完成後我們就可以在Service中使用了。

相關推薦

中介軟體支援setautocommit(false)怎麼辦?

前提 最近在某個公司實習,框架使用的是springmvc+spring+mybatis,具體名字就不說了,所有事務都沒有用無法回滾,導師叫我和db人員對接,我就寫了一個Jdbc的原生的測試測試程式碼如下: try { Class

4.body-parser中介軟體的使用專門處理前端的post請求,同理get請求在本例適用,內含如何自定義中介軟體middleware

使用express框架可以結合中介軟體body-parser方便處理前端傳送過來的資料。(class10) 第一部分: 1.新建目錄後,開啟cmd---進入當前目錄---cnpm install express express-static body-parser   

金笛中介軟體發的簡訊對方收到問題的解決方法

金笛中介軟體一直正常,但近期發的簡訊對方收不到,日誌或資料庫表均顯示已成功傳送,收信正常,將手機卡換到手機中發簡訊,對方能收到。在金笛中介軟體設定視窗中停止服務,然後執行Testmodern.exe,如下圖進行操作: 傳送簡訊,成功。關閉此視窗。回到金笛中介軟體設定視窗,啟動服務如下圖,再

分散式事務中介軟體 TCC-Transaction 原始碼分析 —— Dubbo 支援

1. 概述 本文分享 Dubbo 支援。 TCC-Transaction 通過 Dubbo 隱式傳參的功能,避免自己對業務程式碼的入侵。可能有同學不太理解為什麼說 TCC-Transaction 對業務程式碼有一定的入侵性,一起來看個程式碼例子: 程式碼來自 t

在asp.net core2.1中新增中介軟體以擴充套件Swashbuckle.AspNetCore3.0支援簡單的文件訪問許可權控制

Swashbuckle.AspNetCore3.0 介紹 一個使用 ASP.NET Core 構建的 API 的 Swagger 工具。直接從您的路由,控制器和模型生成漂亮的 API 文件,包括用於探索和測試操作的 UI。 專案主頁:https://github.com/domaindrivendev/Sw

gin使用中介軟體出錯後能用return終止,而應該使用Abort實現

gin使用中介軟體一般是在引擎Engine初始化的時候就繫結,也就是說在需要使用中介軟體才能訪問資源的介面之前幹這些事情。 也就是說,你現在有3個介面,比如一個使用者登入(/api/v1/login), 一個管理員列表(/api/v1/list),一個新增管理員資訊(/ap

【Java進階面試系列之五】訊息中介軟體叢集崩潰,如何保證百萬生產資料丟失?【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! “上一篇講訊息中介軟體的文章《扎心!線上服務宕機時,如何保證資料100%不丟失?》,初步給大家介紹了一個在生產環境中可能遇到的問題,就是你的消費者服務可能會宕機,一旦宕機,你就需要考慮是否會導致

資料庫中介軟體為何不支援join

轉自: http://mp.weixin.qq.com/s/q4DmWjhVmMMSzIP3K_n4Hw    架構師之路 有網友對《假如讓你來設計資料庫中介軟體》一文中,資料庫中介軟體僅僅支援四類SQL存有疑問: partition key普通查詢 parti

學習ASP.NET Core, 怎能瞭解請求處理管道[5]: 中介軟體註冊可以除了可以使用Startup之外,還可以選擇StartupFilter

中介軟體的註冊除了可以藉助Startup物件(DelegateStartup或者ConventionBasedStartup)來完成之外,也可以利用另一個叫做StartupFilter的物件來實現。所謂的StartupFilter是對所有實現了IStartupFilter介面的型別及其物件的統稱。IStart

學習ASP.NET Core,怎能瞭解請求處理管道[1]: 中介軟體究竟是個什麼東西?

ASP.NET Core管道雖然在結構組成上顯得非常簡單,但是在具體實現上卻涉及到太多的物件,所以我們在 “通過重建Hosting系統理解HTTP請求在ASP.NET Core管道中的處理流程”(上篇、中篇、下篇) 中圍繞著一個經過極度簡化的模擬管道講述了真實管道構建的方式以及處理HTTP請求的流程。在本系列

很多C編譯支援bool型,導致出現false和true未定義

解決方法1: 匯入標頭檔案 #include <stdbool.h>     但是有些編譯器沒有這個標頭檔案,那麼可以使用方法2. 解決方法2:自己定義一個bool型           typedef num {false = 0,true = 1}bool

Restorator軟體使exe檔案都能開啟,工作管理員支援此介面

遇到的問題: 下載了一個軟體Restorator(資源修改器),填寫完註冊碼之後,所有的exe檔案都不能打開了,工作管理員不支援此介面打不開。 問題原因: 軟體Restorator關聯exe檔案,執行是通過這個軟體開啟。而這個軟體還沒有彈出來。 解決辦法

網際網路面試必殺:如何保證訊息中介軟體全鏈路資料100%丟失(1)【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! 1、背景引入 這篇文章,我們來聊聊在線上生產環境使用訊息中介軟體技術的時候,從前到後的全鏈路到底如何保證資料不能丟失。 這個問題,在網際網路公司面試的時候高頻出現,而且也是非常現實的生產環境問

網際網路面試必殺:如何保證訊息中介軟體全鏈路資料100%丟失(2)【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! 目錄 (1)前情提示 (2)ack機制回顧 (3)ack機制實現原理:delivery tag (4)RabbitMQ如何感知倉儲服務例項宕機 (5)倉儲服務處理失敗時的訊息重發 (6

一道面試題 訊息中介軟體,怎麼解決訊息的冪等性(訊息怎麼防止被重複消費)

訊息中介軟體中,怎麼解決訊息的冪等性(訊息消費怎麼防止不被重複消費。) 如果SpringBoot和ActiveMQ整合,程式碼不拋異常,標識為消費成。 ActiveMQ 消費程式碼丟擲異常,就會一直重試(10次)。 消費者端丟擲異常,怎麼解決 日誌mongdb(json)、redis、資

網際網路面試必殺:如何保證訊息中介軟體全鏈路資料100%丟失

背景引入 這篇文章,我們來聊聊在線上生產環境使用訊息中介軟體技術的時候,從前到後的全鏈路到底如何保證資料不能丟失。 這個問題,在網際網路公司面試的時候高頻出現,而且也是非常現實的生產環境問題。 如果你的簡歷中寫了自己熟悉MQ技術(RabbitMQ、RocketMQ、Kafka),而且在專案裡有使用的經驗

在websphere中介軟體下更新應用時候更新完成後部分功能能用。

解決方法:把更新包中的web.xml拷貝一份放到中介軟體另一個目錄下。 備註:另一個目錄的位置,參考產品在中介軟體websphere安裝手冊,手冊中有提到。 下面以jact的安裝手冊為例: 如果您使用的中介軟體是Websphere,您還需要把……/WebSphere/App

中介軟體】TOMCAT8支援HTTPS協議

預設情況下,Tomcat是不支援HTTPS協議的,當然該功能TOMCAT是有的  HTTPS協議的配置方法如下,參考網上文件完成,但是網上部分文件有錯誤或者版本不匹配的問題,改過程我是在TOMCAT8上做的,其他版本請自行試驗。 引用:http://blog.csdn.ne

螞蟻金服SOFA開源負責人魯直:只是中介軟體,未來會開源更多

近日,技術媒體Linux中國的創始人王興宇對螞蟻金服SOFA開源負責人魯直,就SOFA 5、ServiceMesh、Serverl

曹工說面試:當應用依賴jar包的A版本,中介軟體jar包依賴B版本,兩個版本相容,這還怎麼玩?

# 背景 大一點的公司,可能有一些組,專門做中介軟體的;假設,某中介軟體小組,給你提供了一個jar包,你需要整合到你的應用裡。假設,它依賴了一個日期類,版本是v1;我們應用也依賴了同名的一個日期類,版本是v2. 兩個版本的日期類,方法邏輯的實現,有一些差異。 舉個例子,中介軟體提供的jar包中,依賴如下