一、JDBC弊端
- 重復(fù)創(chuàng)建鏈接和釋放鏈接蝌诡,造成資源浪費(fèi)溉贿。解決方式:使用連接池
- 出現(xiàn)硬編碼,體現(xiàn)在數(shù)據(jù)庫驅(qū)動(dòng)浦旱,url宇色、用戶名密碼、sql颁湖。解決方式:使用配置文件
- 結(jié)果獲取不方便宣蠕。解決方式:把結(jié)果放到一個(gè)POJO中
二、Mybatis的介紹
MyBatis 本是apache的一個(gè)開源項(xiàng)目iBatis甥捺,2010年這個(gè)項(xiàng)目由apache software foundation 遷移到了google code抢蚀,并且改名為MyBatis 。2013年11月遷移到Github镰禾。iBATIS一詞來源于“internet”和“abatis”的組合皿曲,是一個(gè)基于Java的持久層框架。iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAOs)吴侦。當(dāng)前屋休,最新版本是MyBatis 3.5.1 ,其發(fā)布時(shí)間是2019年4月8日备韧。
MyBatis 是一款支持普通 SQL查詢劫樟,存儲(chǔ)過程和高級(jí)映射的優(yōu)秀持久層框架。MyBatis 消除了幾乎所有的JDBC代碼和參數(shù)的手工設(shè)置以及結(jié)果集的檢索盯蝴。MyBatis 使用簡(jiǎn)單的 XML或注解用于配置和原始映射,將接口和 Java 的POJOs(Plain Ordinary Java Objects听怕,普通的 Java對(duì)象)映射成數(shù)據(jù)庫中的記錄捧挺。
每個(gè)MyBatis應(yīng)用程序主要都是使用SqlSessionFactory實(shí)例的,一個(gè)SqlSessionFactory實(shí)例可以通過SqlSessionFactoryBuilder獲得尿瞭。SqlSessionFactoryBuilder可以從一個(gè)xml配置文件或者一個(gè)預(yù)定義的配置類的實(shí)例獲得闽烙。
用xml文件構(gòu)建SqlSessionFactory實(shí)例是非常簡(jiǎn)單的事情。推薦在這個(gè)配置中使用類路徑資源(classpath resource),但你可以使用任何Reader實(shí)例黑竞,包括用文件路徑或file://開頭的url創(chuàng)建的實(shí)例捕发。MyBatis有一個(gè)實(shí)用類----Resources,它有很多方法很魂,可以方便地從類路徑及其它位置加載資源扎酷。
三、Mybatis架構(gòu)
- mybatis配置 SqlMapConfig.xml遏匆,此文件作為mybatis的全局配置文件法挨,配置了mybatis的運(yùn)行環(huán)境等信息。mapper.xml文件即sql映射文件幅聘,文件中配置了操作數(shù)據(jù)庫的sql語句凡纳。此文件需要在SqlMapConfig.xml中加載。
- 通過mybatis環(huán)境等配置信息構(gòu)造SqlSessionFactory即會(huì)話工廠帝蒿。
- 由會(huì)話工廠創(chuàng)建sqlSession即會(huì)話荐糜,操作數(shù)據(jù)庫需要通過sqlSession進(jìn)行。
- mybatis底層自定義了Executor執(zhí)行器接口操作數(shù)據(jù)庫葛超,Executor接口有兩個(gè)實(shí)現(xiàn)暴氏,一個(gè)是基本執(zhí)行器、一個(gè)是緩存執(zhí)行器巩掺。
- Mapped Statement也是mybatis一個(gè)底層封裝對(duì)象偏序,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個(gè)sql對(duì)應(yīng)一個(gè)Mapped Statement對(duì)象胖替,sql的id即是Mapped statement的id研儒。
- Mapped Statement對(duì)sql執(zhí)行輸入?yún)?shù)進(jìn)行定義,包括HashMap独令、基本類型端朵、pojo,Executor通過Mapped Statement在執(zhí)行sql前將輸入的java對(duì)象映射至sql中燃箭,輸入?yún)?shù)映射就是jdbc編程中對(duì)preparedStatement設(shè)置參數(shù)冲呢。
- 輸入映射(傳入的參數(shù))
支持的數(shù)據(jù)類型:
基本數(shù)據(jù)類型:基礎(chǔ)類型以及包裝類、String
POJO
Map
包裝的POJO:一個(gè)pojo中有pojo屬性
- Mapped Statement對(duì)sql執(zhí)行輸出結(jié)果進(jìn)行定義招狸,包括HashMap敬拓、基本類型、pojo裙戏,Executor通過Mapped Statement在執(zhí)行sql后將輸出結(jié)果映射至java對(duì)象中乘凸,輸出結(jié)果映射過程相當(dāng)于jdbc編程中對(duì)結(jié)果的解析處理過程。
- 輸出映射(產(chǎn)生的結(jié)果類型)
基本數(shù)據(jù)類型:基礎(chǔ)類型以及包裝類累榜、String
POJO
Map
List
四营勤、MyBatis xml配置文件層次結(jié)構(gòu)
properties元素
properties是一個(gè)配置屬性的元素,讓開發(fā)者能在配置文件的上下文中使用它,MyBatis提供3種配置方式:
- property子元素葛作。
- properties配置文件寿羞。
- SqlSessionFactoryBuilder使用Properties文件構(gòu)建。
property子元素
<property name="driver" value="com.mysql.jdbc.Driver"/>
properties配置文件
一般會(huì)使用一個(gè)單獨(dú)的properties配置文件來配置屬性值赂蠢,以方便在多個(gè)配置文件中重復(fù)使用它們绪穆,也方便日后維護(hù)和隨時(shí)修改】湍辏可以通過${key}的形式霞幅,取出在配置文件中配置的值。
<configuration>
<!-- 引入配置文件 -->
<properties resource="datasource.properties"/>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 使用配置文件中的屬性 -->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
</dataSource>
</environment>
</environments>
</configuration>
SqlSessionFactoryBuilder使用Properties文件構(gòu)建
出于安全考慮量瓜,properties配置文件中的賬號(hào)密碼等元素可能是加密的司恳,這個(gè)時(shí)候就需要對(duì)加密的元素進(jìn)行處理。
public static void func() throws Exception {
Properties properties = new Properties();
properties.load(Resources.getResourceAsStream("datasource.properties"));
// 對(duì)原賬號(hào)密碼解密
properties.setProperty("username", decode(properties.getProperty("username")));
properties.setProperty("password", decode(properties.getProperty("password")));
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// SqlSessionFactoryBuilder可以使用一個(gè)InputStream和一個(gè)Properties構(gòu)建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is, properties);
}
三種方式的優(yōu)先級(jí)
MyBatis支持的3種配置方式可能同時(shí)出現(xiàn)绍傲,并且屬性還會(huì)重復(fù)配置扔傅,MyBatis將按照下面的順序來加載:
- 在properties元素體內(nèi)指定的屬性首先被讀取。
- 根據(jù) properties元素中的resource屬性讀取類路徑下屬性文件烫饼,或者根據(jù)url屬性指定的路徑讀取屬性文件猎塞,并覆蓋已讀取的同名屬性。
- 讀取作為build()方法參數(shù)傳遞的屬性杠纵,并覆蓋已讀取的同名屬性荠耽。
因此,通過build()方法參數(shù)傳遞的屬性具有最高優(yōu)先級(jí)比藻,resource/url屬性中指定的配置文件次之铝量,最低優(yōu)先級(jí)的是 properties屬性中指定的屬性。因此银亲,我們盡量不要使用混合的方式來定義配置慢叨,首選的方式是使用properties文件。
五务蝠、environments環(huán)境變量
配置環(huán)境可以注冊(cè)多個(gè)環(huán)境拍谐,每一個(gè)環(huán)境分為兩大部分:一個(gè)是數(shù)據(jù)庫源(dataSource)的配置,另外一個(gè)是數(shù)據(jù)庫事務(wù)(transactionManager)的配置馏段。
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
</dataSource>
</environment>
</environments>
- default:表示默認(rèn)使用哪個(gè)數(shù)據(jù)源
- id:表示數(shù)據(jù)源的名稱
- transactionManager的事務(wù)類型type一共有三種:JDBC轩拨,采用JDBC方式管理事務(wù),獨(dú)立編碼中我們常常使用院喜;MANAGED亡蓉,采用容器方式管理事務(wù),在JNDI數(shù)據(jù)源中常用够坐;自定義寸宵,由使用者自定義數(shù)據(jù)庫事務(wù)管理辦法,適用于特殊應(yīng)用元咙。
- property元素配置數(shù)據(jù)源的各類屬性
- dataSource的type屬性是提供我們對(duì)數(shù)據(jù)厙連接方式的配置:UNPOOLED(非連接池?cái)?shù)據(jù)庫)梯影、POOLED(連接池?cái)?shù)據(jù)庫)、JNDI(JNDI數(shù)據(jù)源)庶香、自定義數(shù)據(jù)源甲棍。
六、數(shù)據(jù)源
MyBatis內(nèi)部為我們提供了3種數(shù)據(jù)源的實(shí)現(xiàn)方式:
- UNPOOLED赶掖,使用org.apache.ibatis.datasource.unpooled.UnpooledDataSource實(shí)現(xiàn)感猛。
- POOLED,使用org.apache.ibatis.datasource.pooled.PooledDataSource實(shí)現(xiàn)奢赂。
- JNDI陪白,使用org.apache.ibatis.datasource.jndi.JndiDataSourceFactory實(shí)現(xiàn)。
七膳灶、數(shù)據(jù)庫事務(wù)
數(shù)據(jù)庫事務(wù)是交由SqlSession去控制的咱士,我們可以通過SqlSession提交或者回滾。在大部分的工作環(huán)境下轧钓,我們都會(huì)使用 Spring框架來控制它序厉。
八、Mybatis解決jdbc編程的問題
- 數(shù)據(jù)庫鏈接創(chuàng)建毕箍、釋放頻繁造成系統(tǒng)資源浪費(fèi)從而影響系統(tǒng)性能弛房,如果使用數(shù)據(jù)庫鏈接池可解決此問題。
解決:在SqlMapConfig.xml中配置數(shù)據(jù)鏈接池而柑,使用連接池管理數(shù)據(jù)庫鏈接文捶。 - Sql語句寫在代碼中造成代碼不易維護(hù),實(shí)際應(yīng)用sql變化的可能較大牺堰,sql變動(dòng)需要改變java代碼拄轻。
解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。 - 向sql語句傳參數(shù)麻煩伟葫,因?yàn)閟ql語句的where條件不一定恨搓,可能多也可能少,占位符需要和參數(shù)一一對(duì)應(yīng)筏养。
解決:Mybatis自動(dòng)將java對(duì)象映射至sql語句斧抱,通過statement中的parameterType定義輸入?yún)?shù)的類型。 - 對(duì)結(jié)果集解析麻煩渐溶,sql變化導(dǎo)致解析代碼變化辉浦,且解析前需要遍歷,如果能將數(shù)據(jù)庫記錄封裝成pojo對(duì)象解析比較方便茎辐。
解決:Mybatis自動(dòng)將sql執(zhí)行結(jié)果映射至java對(duì)象宪郊,通過statement中的resultType定義輸出結(jié)果的類型掂恕。