如果在同一個(gè) ?DataSource
?上同時(shí)使用多個(gè)事務(wù)就需要涉及到 DataSource 資源同步問(wèn)題。舉個(gè)簡(jiǎn)單的例子:
DataSource dataSource = DsUtils.dsMySql();
Connection conn = dataSource.getConnection();
conn.setAutoCommit(false);
JdbcTemplate jdbcTemplate = new JdbcTemplate(conn);
// do something conn
conn.commit();
// do something conn
JdbcTemplate jdbcTemplate = new JdbcTemplate(conn);
conn.commit();
conn.close();
再比如在同一個(gè) ?DataSource
?上開(kāi)啟兩個(gè)相互獨(dú)立的事務(wù):
DataSource dataSource = DsUtils.dsMySql();
Connection tranA = dataSource.getConnection();
tranA.setAutoCommit(false);
JdbcTemplate jdbcTemplate = new JdbcTemplate(tranA);
// do something with tranA
Connection tranB = dataSource.getConnection();
tranB.setAutoCommit(false);
JdbcTemplate jdbcTemplate = new JdbcTemplate(tranB);
// do something with tranB
tranB.commit();
tranA.commit();
使用上面這種方式需要在整個(gè)調(diào)用鏈上傳遞 ?Connection
?以確保不同的業(yè)務(wù)處理邏輯用到相同的數(shù)據(jù)庫(kù)連接。 若 ?Connection
?維護(hù)不當(dāng)就會(huì)造成鏈接泄漏,而這種泄漏通常比較難以發(fā)現(xiàn)和定位的。
HasorDB 內(nèi)置了資源管理器,可以用來(lái)同步上述這種對(duì) ?Connection
?的依賴,但同時(shí)又不需要將其作為參數(shù)傳遞,例如:上面兩個(gè)例子可以換成如下:
例1:
DataSource dataSource = DsUtils.dsMySql();
TransactionManager manager = DataSourceManager.getManager(dataSource);
manager.begin();
JdbcTemplate jdbcTemplate1 = new JdbcTemplate(dataSource);
// do something conn
manager.commit();
manager.begin();
JdbcTemplate jdbcTemplate2 = new JdbcTemplate(dataSource);
// do something conn
manager.commit();
例2:
DataSource dataSource = DsUtils.dsMySql();
TransactionManager manager = DataSourceManager.getManager(dataSource);
manager.begin(); // tranA
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
// do something with tranA
manager.begin(); // tranB
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
// do something with tranB
manager.commit(); // tranB
manager.commit(); // tranA
首先的方式是使用 HasorDB 數(shù)據(jù)庫(kù)操作 API,比如 ?DalSession
?、?JdbcTemplate
?、?LambdaTemplate
?、?@Transactional
?
這些 API 在執(zhí)行數(shù)據(jù)庫(kù)操作時(shí)會(huì)自動(dòng)處理資源的創(chuàng)建、重用以及清理。我們無(wú)需關(guān)心這些具體過(guò)程。
低級(jí)別 API 的特點(diǎn)是缺少了那些自動(dòng)化的管理工作,比如在使用數(shù)據(jù)庫(kù)連接時(shí)需要主動(dòng)釋放它。
Connection conn = DataSourceManager.getConnection(dataSource);
// do something
conn.close();
連接復(fù)用是在低級(jí)別 API 上提供支持的能力,它讓 ?DataSource
?與當(dāng)前線程形成綁定,并提供一個(gè)連接復(fù)用的 ?Connection
?對(duì)象。
Connection conn1 = DataSourceManager.getConnection(dataSource); // new connection
Connection conn2 = DataSourceManager.getConnection(dataSource); // ref ++
Connection conn3 = DataSourceManager.getConnection(dataSource); // ref ++
// do something
conn3.close(); // ref --
conn2.close(); // ref --
conn1.close(); // real close connection
提示
上面 ?
conn1
?、?conn2
?、?conn3
?實(shí)際使用的是同一個(gè) ?Connection
?對(duì)象。
更多建議: