當前位置:編程學習大全網 - 源碼下載 - 如何實現mybatis的sqlsessiontemplate

如何實現mybatis的sqlsessiontemplate

SqlSession sqlSession = null;

try {

sqlSession = sqlSessionFactory.openSession();

//namespace+id

sqlSession.insert("cn.jarjar.dao.BlogMapper.insertBlog", blog);

sqlSession.commit(true)

} catch (Exception e) {

e.printStackTrace();

sqlSession.rollback(true);

} finally {

sqlSession.close();

}

也就是要像原始的java.sql.Connection對象壹樣,必須按照:新建連接->執行SQL->提交(查詢不需要)->如果操作數據存在異常需要回滾->釋放數據庫連接。註意第壹點和最後壹點,每個SqlSession新建之後必須釋放,不然會造成數據庫連接泄露的危險。也就是意味著SqlSession是個有狀態的對象,是無法進行復用的,所以只能局限於request或者方法的範圍,也就是所謂的線程不安全。

現象2:如果使用spring集成mybatis,官方提供了整和包mybatis-spring.jar,如果完成配置之後,使用方式及其簡單,簡單示例如下:

//註入spring中配置的SqlSessionTemplate對象,單例

@Resource(name="sqlSessionTemplate")

public SqlSessionTemplate sqlSessionTemplate;

public void saveTestTrans(){

this.sqlSessionTemplate.selectList("testdomain.selectAnySql", "select * from my_blog where id='1'");

}

這裏的SqlSessionTemplate不僅是單例的,而且不需要手工新建和關閉SqlSession

問題1:

那麽問題來了,為什麽mybatis-spring.jar中的SqlSessionTemplate可以被多個dao復用,而且不會造成數據連接泄露呢,並且還可以自動新建和釋放數據庫連接?官方解答是因為SqlSessionTemplate是線程安全的,也就是確保每個線程使用的sqlSession的唯壹並不互相沖突。

首先看了壹下mybatis-spring的源碼,發現SqlSessionTemplate是通過代理攔截和SqlSessionHolder實現的sqlsession線程安全和自動新建和釋放連接的。看構造函數函數中構建代理類,該代理類實現SqlSession接口,定義了方法攔截器,如果調用代理類實例中實現SqlSession接口定義的方法,該調用則被導向SqlSessionInterceptor的invoke方法,這個方法中自動進行了SqlSession的自動請求和釋放(如果不被spring托管則自己新建和釋放sqlsession,如果被spring管理則使用SqlSessionHolder進行request和relase操作)

以下網址針對SqlSessionTemplate的線程安全特性進行了詳細的探究:blogs.com/daxin/p/3544188.html

問題2:

然後又想到這樣壹個問題,雖然現在幾乎所有項目都使用spring作為java程序的基本框架,如果我不使用spring管理mybatis,僅僅使用原始的mybatis,怎麽樣才能構建壹個和SqlSessionTemplate相似的對象呢?

首先想到必須使用java的treadLocal構建壹個sqlsession的對象,如ThreadLocal sqlSession = new ThreadLocal

()。

經過查找,發現mybatis自身就有這樣壹個類實現了類似的功能,類路徑:org.apache.ibatis.session.SqlSessionManager,但是沒有註釋,可能存在mybatis-spring這種神器之後,mybatis放棄了對這個類的維護。

該類實現了SqlSessionFactory, SqlSession並且在其中定義了壹個treadLocal的sqlssion對象,同時使用了代理攔截進行了sqlsession的自動管理,具體代碼可以自己查閱,對於理解mybatis原理和java的代理機制很有幫助。

那麽寫個簡單的程序驗證壹下SqlSessionManager是否真的可以保證線程安全和自動新建和釋放sqlssion:TestSqlManager.java

private static SqlSession sqlSession;

public static SqlSession getSqlSessionTest(){

if(sqlSession == null){

//構建使用的SqlSessionFactory

SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();

sqlSession = SqlSessionManager.newInstance(sqlSessionFactory);

}

return sqlSession;

}

public static void main(String[] args) throws InterruptedException {

Run run = new Run();

List

threads = new ArrayList

();

for (int i = 0; i < 100; i++) {

Thread t = new Thread(run);

threads.add(t);

System.out.println("thread:{"+t.getName()+"}, start");

t.start();

}

for (Thread t : threads) {

System.out.println("thread:{"+t.getName()+"},join");

t.join();

}

}

我本機裝的mysql,通過監控語句:select SUBSTRING_INDEX(host,’:’,1) as ip , count(*) from information_schema.processlist group by ip;發現執行過程中存在連接並發的情況,但是執行之後全部釋放掉了。

  • 上一篇:現在學計算機,有前途嗎?我能怎麽做呢?工資壹般是多少?
  • 下一篇:薅羊毛是什麽意思?
  • copyright 2024編程學習大全網