MyBatis使用場景
對比Hibernate和MyBatis是我們常見的話題,Hibernate作為常用的ORM框架,它使用起來簡單易懂,對於SQL語言的封裝,讓對於SQL並不是很熟練的程序員也可以輕松地開發DAO層,IDE也有對應的工具來反向生成,所以開發效率較快,Hibernate也提供了緩存,級聯等高級功能。但是其缺點在於:
1.對於需要SQL優化的場景,如果SQL復雜,Hibernate方法的封裝也派不上用場,還是需要使用原生SQL,而原生SQL返回的是一個Object數組,接下來就是需要我們自己手工完成封裝了。
2.Hibernate是一個全表映射的框架,所以更新和查詢時,如果我們只需要操作表中某些字段,就無法做到。
3.不能有效支持存儲過程
所以Hibernate適用於場景不復雜的,對於性能要求並不高的場景。
可以說MyBatis是一個半映射的框架,它也支持緩存,級聯等操作,缺點就在於需要你提供映射規則和SQL,工作量比Hibernate要大。MyBatis雖然開發不如Hibernate效率高,但是其靈活,可SQL優化的特點很吸引人,正因為此,在於大數據,高並發移動互聯網項目中較為常用。
MyBatis的組件
SqlSessionFactoryBuilder(構造器):它可以根據配置來獲得SqlSessionFactory
SqlSessionFactory(工廠接口):依靠接口創建SqlSession
我們這里再對比一下Mybatis與Hibernate之間創建session工廠所使用方法的不同:
Hibernate中創建方法
Configuration cfg=new Configuration().configure("hibernate.cfg.xml"); //加載hibernate配置文件 SessionFactory sessionFactory=cfg.buidSessionFactory();
Mybatis中創建方法
String resource="mybatis-config.xml"; InputStream inputStream=Resources.getResourceAsStream(resource); //加載mybatis配置文件 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession:是一個既可以發送SQL去查詢並返回結果,也可以用來獲得Mapper接口
hibernate和Mybatis都是使用Session工廠中的方法來創建會話的,巧合的是這兩者的方法名都為openSession
SQL Mapper:它是一個MyBatis較為推薦的方式,通過寫接口替代傳統DAO開發的方式。它是由Java接口和XML文件(或注解)構成
生命周期
SqlSessionFactoryBuilder的作用就是構建SqlSessionFactory,可以使用XML或注解的方式構建一個或多個SqlSessionFactory,構建成功之后,就失去了存在的意義,應該將其回收,所以,將其生命周期限制在方法局部中。
SqlSessionFactory是用來構建SqlSession的,如果我們多次創建同一個SqlSessionFactory,在每一次創建的時候,都會打開使用數據庫資源,那么連接資源很快就會被耗盡,所以應該使用單例模式來構建。類比於Hibernate,Hibernate也是通過SessionFactory來構建Session的,都應該是使用了工廠模式。
SqlSession相當於JDBC中的Connection,其是線程不安全的,所以在多線程的時候需要當心,在操作數據庫的時候需要注意隔離級別,數據庫鎖等問題。它在每次使用過后應該及時關閉,長期存在,就會減少數據庫連接資源,對系統性能影響很大。
Mapper是一個接口,沒有實現類,它的作用是發送SQL查詢,並返回結果,或者是通過SQL修改數據庫中的記錄,所以應該存在於一個SqlSession的事務方法范圍中。
SqlSessionFactory應該是單例的
SqlSessionFactory應該是單例的,所以我們就寫一個單例的工廠工具類,在以后與Spring整合之后就不在需要了,那時我們是在applicationContext.xml文件中配置了SqlSessionFactoryBean作為SessionFactory的。
import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class SQLSessionFactoryUtil { //SqlSessionFactory對象 private static SqlSessionFactory sqlSessionFactory; //當前類的Class對象作為線程鎖 private static final Class CLADD_LOCK=SqlSessionFactory.class; /** * 私有化構造 */ private SQLSessionFactoryUtil() {} /** * 構建SQLSessionFactory */ public static SqlSessionFactory initSqlSessionFactory() { //MyBatis配置文件 String resource="mybatis-config.xml"; InputStream inputStream=null; try { inputStream=Resources.getResourceAsStream(resource); }catch (Exception e) { e.printStackTrace(); } synchronized (CLADD_LOCK) { //加上線程鎖,避免在多線程環境下多次初始化造成對象不唯一 if(sqlSessionFactory==null) { sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); } } return sqlSessionFactory; } /** * 打開sqlsession */ public static SqlSession openSqlSession() { if(sqlSessionFactory==null) { initSqlSessionFactory(); } return sqlSessionFactory.openSession(); } }