Spring全家桶相關
1.mybatis工作原理
一、相較於Hibernate,mybatis的優勢在哪裡?
Hibernate缺點:
1、執行效率低,記憶體佔用比較嚴重
2、針對單一物件的增刪改查,適合Hibernate,而Hibernate在批量操作時處於弱勢
3、雖然Hibernate引入一二級快取、lazyload、查詢快取等更多優化空間(對於那些改動 不大且經常使用的資料,可將他們放入快取中),但Hibernate對於持久層封裝過於完 整,導致開發人員無法對sql進行優化,不適用於大型專案
mybatis優點:
1、程式碼量大大減少,開發效率高
2、 MyBatis相當靈活,SQL寫在XML裡,從程式程式碼中徹底分離,降低耦合度,便於統 一管理和優化,並可重用
3、執行效率高
二、mybatis原理
下面是mybatis的一個原理圖,看懂這個圖對理解mybatis工作原理很重要:
上面的原理圖看的不是很清晰,下面再詳細介紹一下mybatis的主要成員:
1、Configuration
MyBatis所有的配置資訊都儲存在Configuration物件之中,配置檔案的大部分配置都會儲存到該類中
2、SqlSession(工廠模式創建出來)
作為MyBatis工作的主要頂層API,表示和資料庫互動時的會話,完成必要資料庫增刪改查功能
3、Executor
MyBatis執行器,是MyBatis 排程的核心,負責SQL語句的生成和查詢快取的維護
StatementHandler 封裝了JDBC Statement操作,負責對JDBC statement 的操作,如設定引數等
4、ParameterHandler
負責對使用者傳遞的引數轉換成JDBC Statement 所對應的資料型別
5、ResultSetHandler
負責將JDBC返回的ResultSet結果集物件轉換成List型別的集合
6、TypeHandler
負責java資料型別和jdbc資料型別(也可以說是資料表列型別)之間的對映和轉換
7、MappedStatement
MappedStatement維護一條<select|update|delete|insert>節點的封裝
8、SqlSource
負責根據使用者傳遞的parameterObject,動態地生成SQL語句,將資訊封裝到BoundSql物件中,並返回
9、BoundSql
表示動態生成的SQL語句以及相應的引數資訊
下面介紹一下mybatis的工作流程:
首先,mybatis的增刪改查這些資料庫操作都是基於sqlsession類的,SqlSession又是由SqlSessionFactory類創建出來的(這裡採用了java設計模式中的工廠模式),而SqlSessionFactory是由SqlSessionFactoryBuilder建立的,SqlSessionFactoryBuilder要想建立SqlSessionFactory,必須要有原料(即mybatis配置檔案),下面是建立SqlSession的程式碼:
//載入classpath路徑下的mybatis配置檔案
InputStream in=Resources.getResourceAsStream(“mybatis-config.xml”);
//根據載入配置檔案產生的輸入流,來建立一個SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//根據SqlSessionFactory建立SqlSession
SqlSession session = sessionFactory.openSession();
下面介紹這幾個重要物件的作用域和生命週期
1、SqlSessionFactoryBuilder
這個類可以被例項化、使用和丟棄,一旦建立了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 例項的最佳作用域是方法作用域(也就是區域性方法變數)。你可以重用 SqlSessionFactoryBuilder 來建立多個 SqlSessionFactory 例項,但是最好還是不要讓其一直存在以保證所有的 XML 解析資源開放給更重要的事情。
2、SqlSessionFactory
SqlSessionFactory 一旦被建立就應該在應用的執行期間一直存在,沒有任何理由對它進行清除或重建。使用 SqlSessionFactory 的最佳實踐是在應用執行期間不要重複建立多次。因此 SqlSessionFactory 的最佳作用域是應用作用域。有很多方法可以做到,最簡單的就是使用單例模式或者靜態單例模式
3、SqlSession
每個執行緒都應該有它自己的 SqlSession 例項。SqlSession 的例項不是執行緒安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。絕對不能將 SqlSession 例項的引用放在一個類的靜態域,甚至一個類的例項變數也不行。sqlSession在每次用完之後必須關閉它
三、mybatis快取機制
1、一級快取
MyBatis一級快取是基於sqlSession的,sqlSession物件有一個HashMap用於儲存快取資料,此HashMap是當前會話物件私有的,別的SqlSession會話物件無法訪問。一級快取預設是開啟的,且無法關閉。增刪改操作會清空當前sqlSession裡的快取
2、二級快取
MyBatis二級快取是mapper級別的快取,同一個namespace共用這一個快取,所以對SqlSession是共享的,二級快取是預設關閉的。
如何配置二級快取?只需要在sql對映檔案中新增即可
測試程式碼:
/*
- 注意:被快取的資料要實現序列化介面(在這裡將Book.java實現序列化介面),否則會出現異常
- 另外,當某一個sqlSession修改了共享的快取資料之後,二級快取也會清空
*/
SqlSession session_1 = MyBatisUtil.getSession();
BookDao mapper_1 = session_1.getMapper(BookDao.class);
mapper_1.listBook();
//注意,必須提交才能將資料放進二級快取
session_1.commit();
SqlSession session_2 = MyBatisUtil.getSession();
BookDao mapper_2 = session_2.getMapper(BookDao.class);
mapper_2.listBook();
這裡只是為了測試二級快取的原理,所以MyBatisUtil類如何獲取SqlSession的程式碼就沒有貼上進來了。
Mybatis快取參考
https://www.cnblogs.com/happyflyingpig/p/7739749.html