不管你信不信,事實證明ibatis 對資料庫的任何操作都加了事務,無論你是否使用SqlMapClient的startTransaction方法,在ibatis中事務總是開啟的,而且無法通過配置來改變它,慶幸的是還有一種方法來繞過事務,否則spring也該無語了。它的startTransaction方法只是讓我們來控制更大範圍的事務而已。例如:
publicstaticvoid test1() throws SQLException, IOException { Reader reader = Resources.getResourceAsReader("sql-map-config.xml"); SqlMapClient smc = SqlMapClientBuilder.buildSqlMapClient(reader); List list = smc.queryForList("Test.testQuery", null); System.out.println(list.size()); }
上面代碼已經具有隱含交易了。如果URL中不加SelectMethod=cursor的話就會報錯,因為開事務必須加SelectMethod=cursor。至於如何繞過事務我稍後在講,或許有些朋友會問有事務有什麼不好嗎,先不說好不好的問題,我先說一種情況這種情況開了事務根本就無法執行,那就是sqlserver的分散式查詢,比如A機器上的a庫的一個視圖bview是B機器上的b表,那麼如果查詢 select * from bview 時開啟了事務,就會報錯,原因是沒有開啟分散式交易,像這種情況根本就沒有必要開啟分散式交易,因為我有100個需求但都是查詢。要事務何用? 另外因為ibatis的另類交易管理,導致URL中必須添加SelectMethod=cursor不開遊標會報錯,本來一個可選的配置在ibatis裡面成了必選項。 JDBC.DefaultAutoCommit選項成了雞肋,這僅僅是一個預設值而已在下面的寫法中它才能派上用場。由於spring的出現,或許現在已經沒有人單獨使用ibatis了,眾所周知spring的強大聲明式事務,在沒有配置聲明式事務之前包括hibernate,ibatis在內的orm持久層都是沒有事務的狀態,那麼spring是如何繞過ibatis自身交易管理的呢,網路是強大的,搜尋引擎是強大的,不少網友將spring控制事務的程式碼片段貼了出來,從一塊塊片段中發現了線索,經測試證明是可以繞過ibatis自己的事務,自己來控制事務,就是利用SqlMapClient的setUserConnection方法,看到這個方法名有所感悟,其實這個方法在hibernate也是有的,對外提供給開發人員自己控制connection的權利,不過脫離了spring單獨使用ibaits這麼幹是不是太麻煩了?
/** * * Description:繞過ibatis交易管理,做分散式查詢的情況 * * @throws SQLException * @throws IOException * @mail sunyujia@yahoo.cn * @since:Jul 13, 2008 5:28:32 PM */public static void test2() throws SQLException, IOException {Reader reader = Resources.getResourceAsReader("sql-map-config.xml");SqlMapClient smc = SqlMapClientBuilder.buildSqlMapClient(reader);Connection conn = null;List lits = null;boolean isAutoCommit = false;try {conn = smc.getDataSource().getConnection();isAutoCommit = conn.getAutoCommit();conn.setAutoCommit(true);smc.setUserConnection(conn);lits = smc.queryForList("Test.testQuery", null);} finally {try {conn.setAutoCommit(isAutoCommit);} finally {conn.close();}}System.out.println(lits.size());}
通過這種方法,JDBC.DefaultAutoCommit這個選項也算是個有用的參數了。 不過,ibatis這種交易處理手段是不是太晦澀了些。