MyBatis之八:需要说明的几个java api的生命周期以及封装
學習mybatis不得不了解SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession。這里主要是講解它們的生命周期以及一般最佳實踐。?一般來說對象的生命周期也就是對象創建到銷毀的過程,如果在這個過程中,如果實現的代碼質量不佳,那么很容易造成程序上的錯誤或者效率的降低。
1、SqlSessionFactoryBuilder
SqlSessionFactoryBuilder可以被jvm虛擬機所實例化、使用或者銷毀。一旦使用SqlSessionFactoryBuilder對象創建SqlSessionFactory后,SqlSessionFactoryBuilder類就不需要存在了,也就是,不需要保持對象的狀態,可以隨意的由jvm銷毀。因此SqlSessionFactoryBuilder對象的最佳使用范圍是方法內部。
? 2、SqlSessionFactory
SqlSessionFactory對象是由SqlSessionFactoryBuilder創建。一旦創建SqlSessionFactory類的實例,該實例應該在應用程序執行期間都存在,根本不需要每一次操作數據庫時都創建,所以其最佳實踐方式就是單例模式,或者使用Spring框架來實現單例模式對SqlSessionFactory對象進行有效管理(后續會講解)。
? 3、SqlSession
SqlSession對象由SqlSessionFactory類創建,需要注意的是,每個線程都應該有它自己的SqlSession實例。SqlSession的實例不能共享,是線程不安全的,其實我們去扒看SqlSession接口定義,可以發現,里面定義了數據的增刪改查以及事務處理以及實例對象的關閉。那么很顯然在操作該對象的時候必須要保持其線程安全,不然在并發情況下肯定會亂套。或者將SqlSession實例對象存放在一個類的靜態字段甚至是實例字段中。
4、簡單封裝
由1、2、3得知,SqlSessionFactoryBuilder會被jvm自動銷毀、SqlSessionFactory不需要每次操作數據庫都創建、SqlSession必須是線程安全的,那么針對這3點,以下做了一個簡單封裝。
?SyncSqlSessionFactory類主要是獲取SqlSessionFactory單例對象
package com.mybatis.util;import java.io.IOException; import java.io.InputStream;import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class SyncSqlSessionFactory {private static SqlSessionFactory sqlSessionFactory;private SyncSqlSessionFactory() {}synchronized public static SqlSessionFactory getSqlSessionFactory() {try {if (sqlSessionFactory == null) {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}} catch (IOException e) {e.printStackTrace();}return sqlSessionFactory;} }SafeSqlSessionUtil類保證SqlSession線程安全的前提下封裝了事務的回滾提交操作。
package com.mybatis.util;import org.apache.ibatis.session.SqlSession;public class SafeSqlSessionUtil {private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();public static SqlSession getSqlSession() {SqlSession sqlSession = threadLocal.get();return sqlSession == null ? SyncSqlSessionFactory.getSqlSessionFactory().openSession() : sqlSession;}public static void commit() {if (threadLocal.get() != null) {threadLocal.get().commit();threadLocal.get().close();threadLocal.set(null);}}public static void rollback() {if (threadLocal.get() != null) {threadLocal.get().rollback();threadLocal.get().close();threadLocal.set(null);}} }5、使用示例
try {SqlSession sqlSession = SafeSqlSessionUtil.getSqlSession();//基本操作sqlSession.delete("");sqlSession.update("");sqlSession.select("",null);} catch (Exception e) {SafeSqlSessionUtil.rollback();}finally{SafeSqlSessionUtil.commit();}6、需要說明的地方
synchronized:如果某個synchronized方法是static的,那么當線程訪問該方法時,它鎖的并不是synchronized方法所在的對象,而是synchronized方法所在的類所對應的Class對象。Java中,無論一個類有多少個對象,這些對象會對應唯一一個Class對象,因此當線程分別訪問同一個類的兩個對象的兩個static,synchronized方法時,它們的執行順序也是順序的,也就是說一個線程先去執行方法,執行完畢后另一個線程才開始。
ThreadLocal:線程級別的隔離。它通過為每個線程提供一個獨立的變量副本解決了變量并發訪問的沖突問題。多數情況下ThreadLocal比直接使用synchronized同步機制解決線程安全問題更簡單,更方便,且結果程序擁有更高的并發性。
理解得更加通俗一點就是一個是鎖機制進行時間換空間,一個是存儲拷貝進行空間換時間。
轉載于:https://www.cnblogs.com/wucj/p/5162213.html
總結
以上是生活随笔為你收集整理的MyBatis之八:需要说明的几个java api的生命周期以及封装的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA代码走查审查规范
- 下一篇: 复盘二进制的习题(2)