新聞中心
一、MyBatis簡(jiǎn)介
MyBatis的前身是Apache的一個(gè)開源項(xiàng)目iBatis,2010年這個(gè)項(xiàng)目由apache software foundation 遷移到了google code,并且改名為MyBatis。2013年11月遷移到GitHub,因此目前MyBatis是由GitHub維護(hù)的。
創(chuàng)新互聯(lián)建站是一家專注于網(wǎng)站建設(shè)、做網(wǎng)站與策劃設(shè)計(jì),白城網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:白城等地區(qū)。白城做網(wǎng)站價(jià)格咨詢:028-86922220
??同樣作為持久層框架的Hibernate在前些年非常的火,它在配置了映射文件和數(shù)據(jù)庫連接文件后就可以通過Session操作,它甚至提供了HQL去操作POJO進(jìn)而操作數(shù)據(jù)庫的數(shù)據(jù),幾乎可以使編程人員脫離sql語言。可是為什么MyBatis卻越來越受歡迎呢?我們稍稍總結(jié)如下:
Hibernate:
1.不方便的全表映射,比如更新時(shí)需要發(fā)送所有的字段;
??2.無法根據(jù)不同的條件組裝不同sql;
??3.對(duì)多表關(guān)聯(lián)和復(fù)制sql查詢支持較差;
4.有HQL但性能較差,做不到sql優(yōu)化;
- ?5.不能有效支持存儲(chǔ)過程;
在當(dāng)今的大型互聯(lián)網(wǎng)中,靈活、sql優(yōu)化,減少數(shù)據(jù)的傳遞是最基本的優(yōu)化方法,但是Hibernate卻無法滿足我們的需求,而MyBatis提供了更靈活、更方便的方法。在MyBatis里,我們需要自己編寫sql,雖然比Hibernate配置要多,但是是MyBatis可以配置動(dòng)態(tài)sql,也可以優(yōu)化sql,且支持存儲(chǔ)過程,MyBatis幾乎能做到 JDBC 所能做到的所有事情!憑借其高度靈活、可優(yōu)化、易維護(hù)等特點(diǎn),成為目前大型移動(dòng)互聯(lián)網(wǎng)項(xiàng)目的首選框架。
二:開發(fā)環(huán)境、流程及生命周期
1.開發(fā)環(huán)境
1.1 導(dǎo)入依賴jar包
導(dǎo)入mybatis的jar包,如果采用Maven進(jìn)行部署,只需導(dǎo)入mybatis坐標(biāo)。
導(dǎo)入數(shù)據(jù)庫驅(qū)動(dòng)jar包或坐標(biāo)。
代碼調(diào)試階段可導(dǎo)入日志工具jar包或坐標(biāo),如log4j。
- 導(dǎo)入Junit單元測(cè)試坐標(biāo)。
1.2 創(chuàng)建mybatis的主配置文件
??在resources目錄下建立一個(gè)名字為mybatis-config.xml(名稱隨意)配置文件,編寫所需配置信息。
1.3 準(zhǔn)備實(shí)體類和表結(jié)構(gòu)
??遵循開發(fā)規(guī)范:
類屬性命名盡量和表字段保持一致。
實(shí)體類實(shí)現(xiàn)序列化接口。
- 實(shí)體類屬性使用包裝類型定義,如Integer。
Tips:?有時(shí)可以考慮通過定義時(shí)初始化來避免可能的空指針異常!
如:private List
1.4 創(chuàng)建Mapper接口(Dao接口)建立接口方法和sql映射文件
創(chuàng)建Mapper接口,在內(nèi)定義CRUD方法。
??Tips:方法名唯一,需要在對(duì)應(yīng)的mapper.xml文件中配置id。
在resources下創(chuàng)建sql映射文件。
??Tips:同對(duì)應(yīng)的Mapper接口保持包結(jié)構(gòu)及命名一致。
??如:Mapper接口: cn.dintalk.dao.UserMapper
??對(duì)應(yīng)配置文件:cn.dintalk.dao.UserMapper.xml
1.5 將映射文件加入到mybatis主配置文件中
將映射文件通過引入的方式加入到mybatis的主配置文件中。
??Tips:?所有映射文件會(huì)隨主配置文件在程序運(yùn)行時(shí)加入內(nèi)存,任一映射文件出?錯(cuò)都會(huì)導(dǎo)致整個(gè)環(huán)境報(bào)錯(cuò)!(初學(xué)者經(jīng)常搞混resultType和resultMap)。
1.6 編寫代碼進(jìn)行CRUD操作
在映射文件中編寫sql進(jìn)行crud操作,在單元測(cè)試中,或service層中調(diào)用方法!
2.開發(fā)流程
環(huán)境搭建好后開發(fā)基本流程為:
接口定義方法 。
Mapper.xml文件中編寫sql。
- 單元測(cè)試或service調(diào)用。
3.生命周期
MyBatis的核心組件:
SqlSessionFactoryBuilder(構(gòu)造器):根據(jù)配置信息或代碼生成SqlSessionFactory
SqlSessionFactory(工廠接口):依靠工廠來生成SqlSession(會(huì)話)。
SqlSession(會(huì)話): 既可以發(fā)生sql去執(zhí)行并返回結(jié)果,也可以獲取Mapper的接口
SQL Mapper:它是MyBatis新設(shè)計(jì)的組件,它是由一個(gè)java接口和xml文件(或注解)構(gòu)成的,需要給出對(duì)應(yīng)的sql和映射規(guī)則。它負(fù)責(zé)發(fā)送sql去執(zhí)行,并返回結(jié)果。
??正確理解并掌握上述核心組件的生命周期可以讓我們寫出高效的程序,還可避免帶來嚴(yán)重的并發(fā)問題。
3.1 SqlSessionFactoryBuilder
??其作用就是利用xml或java編碼獲得資源來構(gòu)建SqlSessionFactory對(duì)象,構(gòu)建成功就失去了存在的意義,將其回收。所以它的生命周期只存在于方法的局部。
3.2 SqlSessionFactory
??SqlSessionFactory的作用是創(chuàng)建SqlSession,而SqlSession就是一個(gè)會(huì)話,相當(dāng)于JDBC中的Connection對(duì)象,每次訪問數(shù)據(jù)庫都需要通過SqlSessionFactory創(chuàng)建SqlSession,所以SqlSessionFactory應(yīng)該在MyBatis應(yīng)用的整個(gè)生命周期中。我們使每一個(gè)數(shù)據(jù)庫只對(duì)應(yīng)一個(gè)SqlSessionFactory(單例模式)。
3.3 SqlSession
??SqlSession是一個(gè)會(huì)話,相當(dāng)于JDBC的一個(gè)Connection對(duì)象,它的生命周期應(yīng)該是在請(qǐng)求數(shù)據(jù)庫處理事務(wù)的過程中。是一個(gè)線程不安全的對(duì)象,涉及多線程時(shí)格外當(dāng)心。此外,每次創(chuàng)建的SqlSession都必須及時(shí)關(guān)閉它。
3.4 Mapper
??Mapper是一個(gè)接口,沒有任何實(shí)現(xiàn)類,其作用是發(fā)送sql,返回我們需要的結(jié)果,或者執(zhí)行sql修改數(shù)據(jù)庫數(shù)據(jù),因此它也因該在一個(gè)SqlSession事務(wù)方法之內(nèi),是一個(gè)方法級(jí)別的東西。就如同 JDBC中的一條sql語句的執(zhí)行,它的最大范圍和SqlSession是相同的。
public class MyBatisUtil {
private static SqlSessionFactory build =null;
static {
try { //使用MyBatis的Resources加載資源獲得輸入流,構(gòu)建工廠
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
build = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
throw new RuntimeException("資源文件加載失敗!");
}
}
//使用工廠生產(chǎn)sqlSession
public static SqlSession openSession(){
return build.openSession();
}
}
SqlSession使用方法
//1.定義sqlSession
SqlSession sqlSession = null;
try {
sqlSession = openSession();
//2.獲取映射器
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//3.some code like 'User u = mapper.findById(id);'
//4.sqlSession不提交默認(rèn)回滾!增刪改需格外注意!
sqlSession.commit();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
三:映射器
1.映射器元素簡(jiǎn)介
我們可以在映射器中定義哪些元素,以及它們有何作用呢?
元素名稱 | 作用 |
---|---|
insert | 定義插入語句 |
delete | 定義刪除語句 |
update | 定義修改語句 |
select | 定義查詢語句 |
parameterMap | 定義參數(shù)映射關(guān)系 |
resultMap | 提供從數(shù)據(jù)庫結(jié)果集到POJO映射規(guī)則 |
cache | 配置當(dāng)前命名空間的緩存配置(二級(jí)緩存) |
sql | 定義部分sql,各個(gè)地方都可引用 |
cache-ref | 引用其他命名空間的緩存配置 |
在各個(gè)元素當(dāng)中又有相當(dāng)多的屬性配置項(xiàng),這里不多贅述,通過下一節(jié)掌握常用的內(nèi)容即可。這里特別說明sql元素的使用:
id, name, password
2.簡(jiǎn)單CRUD操作
2.1添加用戶
INSERT into users (name,password) VALUES (#{name},#{password});
2.2添加用戶并返回?cái)?shù)據(jù)庫中的主鍵
insert into users (name,password) values(#{name},#{password});
select last_insert_id();
insert into users (name,password) values(#{name},#{password});
2.3修改/刪除用戶
update users set name=#{name},password=#{password} where uid=#{uid};
delete from users where uid=#{uid};
2.4查詢用戶
四:動(dòng)態(tài)sql和高級(jí)查詢
1.動(dòng)態(tài)sql
?? MyBatis的動(dòng)態(tài)sql包含這些元素:if | choose(when ohterwise) |trim(where set) | foreach ,通過這些元素來動(dòng)態(tài)組裝sql語句,主要是增改查操作。(實(shí)際開發(fā)中,嚴(yán)禁使用select 操作。這里為了簡(jiǎn)便使用select 演示)!
1.1使用 if,實(shí)現(xiàn)動(dòng)態(tài)sql,完成查詢操作
1.2使用if,實(shí)現(xiàn)動(dòng)態(tài)sql,完成更新操作
update users set
name=#{name},
password=#{password},
uid=#{uid} where uid=#{uid};
1.3使用if,實(shí)現(xiàn)動(dòng)態(tài)sql,完成添加操作
insert into users (name,
password,
email,phoneNumber,birthday) values(#{name},
#{password},
#{email},#{phoneNumber},#{birthday});
1.4使用choose when otherwise,實(shí)現(xiàn)動(dòng)態(tài)sql,完成查詢操作
1.5使用if和where,實(shí)現(xiàn)動(dòng)態(tài)sql,完成查詢操作 ★★★
1.6使用if和set,實(shí)現(xiàn)動(dòng)態(tài)sql,完成更新操作 ★★
update users
name=#{name},
password=#{password},
uid=#{uid},
where uid=#{uid};
1.7使用foreach,實(shí)現(xiàn)動(dòng)態(tài)sql,完成根據(jù)id集合、數(shù)組等的查詢操作
1.8bind元素
bind元素的作用是通過OGNL表達(dá)式自定義一個(gè)上下文變量,這樣更方便我們使用。在進(jìn)行模糊查詢的時(shí)候,如果是MySQL數(shù)據(jù)庫,我們常用concat函數(shù)用“%”和參數(shù)連接。然而在Oracle數(shù)據(jù)則是用連接符號(hào)“||”。這樣sql就需要提供兩種形式去實(shí)現(xiàn)。用bind元素,我們就不必使用數(shù)據(jù)庫語言,只要使用MyBatis的語言即可與所需參數(shù)相連。
2.高級(jí)查詢(多表查詢)
2.1一對(duì)多關(guān)聯(lián)查詢
2多對(duì)一關(guān)聯(lián)查詢(別名映射|resultMap映射|resultMap結(jié)合association映射)
2.3多對(duì)多關(guān)聯(lián)查詢
五:嵌套查詢和延遲加載
1.加載策略
??在關(guān)聯(lián)查詢時(shí),對(duì)于關(guān)聯(lián)的一方是否查詢出來,要根據(jù)業(yè)務(wù)需求而定。不能通過編碼方式進(jìn)行策略的改變,而應(yīng)該通過修改配置文件改變加載策略。可以使用嵌套查詢(分步查詢)。
2.嵌套查詢
2.1根據(jù)多的一方,嵌套查詢少的一方
2.2根據(jù)少的一方,嵌套查詢多的一方
3.配置延遲加載
3.1全局配置,修改mybatis.xml主配置文件
啟用延遲加載后,mybatis默認(rèn)有toString、equals等4個(gè)觸發(fā)加載的方法。我們也可以將其覆蓋掉。
延遲加載,即用到關(guān)聯(lián)數(shù)據(jù)的時(shí)候再去查,不用就不查。(service層中會(huì)有很多方法調(diào)用dao方法,根據(jù)service層中的實(shí)際需求動(dòng)態(tài)調(diào)整加載策略,高效利用資源!)
3.2每個(gè)association和collection都有fetchType屬性
fetchType="lazy"(默認(rèn)) | eager
lazy : 支持延遲加載
- eager : 立即加載
六:事務(wù)控制及數(shù)據(jù)源
1.事務(wù)控制
??通過 JDBC 可以手動(dòng)控制:
??Connection.setAutoCommit(false);
??Connection.commit();
??Connection.rollback();// 開啟事務(wù)后,未提交會(huì)自動(dòng)回滾!
相當(dāng)于使用 JDBC 進(jìn)行事務(wù)控制:(增刪改時(shí)不提交會(huì)自動(dòng)回滾!)
獲取SqlSession時(shí):SqlSessionFactory.openSession(); // 手動(dòng)控制事務(wù) ★
??SqlSessionFactory.openSession(true); //自動(dòng)提交事務(wù)
2.數(shù)據(jù)源
2.1mybatis內(nèi)置數(shù)據(jù)源
mybatis內(nèi)置了三種數(shù)據(jù)源:
UNPOOLED :不帶有池(連接池)|學(xué)習(xí)時(shí)用
POOLED : 帶有池的 | 實(shí)際生產(chǎn)環(huán)境使用
JNDI : mybatis提供的JndiDataSourceFactory來獲取數(shù)據(jù)源
2.2內(nèi)部原理
POOLED對(duì)應(yīng)的是PooledDataSource數(shù)據(jù)源,PooledDataSourceFactory用來生產(chǎn)帶有池的數(shù)據(jù)源。
UNPOOLED對(duì)應(yīng)的是UnpooledDataSource數(shù)據(jù)源,UnpooledDataSourceFactory用來生產(chǎn)不帶有池的數(shù)據(jù)源。
2.3使用Druid等第三方數(shù)據(jù)源(以Druid為例)
com.alibaba
druid
1.1.14
第二步:編寫工廠類,用來產(chǎn)生Druid的數(shù)據(jù)源,一般選擇繼承UnpooledDataSourceFactory
public class DataSourceFactory extends UnpooledDataSourceFactory{
public DataSourceFactory(){
this.dataSource = new DruidDataSource();//創(chuàng)建druid數(shù)據(jù)源
}
}
第三步:在mybatis-config.xml中進(jìn)行配置
七:MyBatis的緩存
1.系統(tǒng)緩存
MyBatis對(duì)緩存提供支持,但是在沒有配置的默認(rèn)情況下,它只開啟一級(jí)緩存。
1.1一級(jí)緩存
??一級(jí)緩存只是相對(duì)于同一個(gè)SqlSession而言的。使用SqlSession第一次查詢后,MyBatis會(huì)將其放在緩存中,以后再查詢時(shí),如果沒有聲明需要刷新,且緩存未超時(shí)的情況下,SqlSession都只會(huì)取出當(dāng)前緩存的數(shù)據(jù),而不會(huì)再次發(fā)送Sql到數(shù)據(jù)庫。
1.2二級(jí)緩存
??二級(jí)緩存是在SqlSessionFactory層面上的,可以將緩存提供給各個(gè)SqlSession對(duì)象共享。
Mapper.xml文件中
Tips:
一級(jí)緩存中存放的是對(duì)象本身,是同一個(gè)對(duì)象!
- 二級(jí)緩存中存放的是對(duì)象的拷貝,對(duì)象所屬類必須實(shí)現(xiàn)jav.io.Serializable接口!
eviction: 代表的是緩存回收策略,目前MyBatis提供以下策略:
??(1)LRU, 最近最少使用的,移除最長時(shí)間不用的對(duì)象。
??(2)FIFO, 先進(jìn)先出,按對(duì)象進(jìn)入緩存的順序來移除它們。
??(3)SOFT,軟引用,移除基于垃圾回收器狀態(tài)和軟引用規(guī)則的對(duì)象。
??(4)WEAK,弱引用,更積極地移除基于垃圾收集器狀態(tài)和弱引用規(guī)則的對(duì)象。
flushInterval: 刷新間隔時(shí)間,單位為毫秒。
size: 引用數(shù)目,代表緩存最多可以存儲(chǔ)多少個(gè)對(duì)象。
- readOnly: 只讀,意味著緩存數(shù)據(jù)只讀。
2.自定義緩存
?? 系統(tǒng)緩存是MyBatis應(yīng)用機(jī)器上的本地緩存,我們也可以使用緩存服務(wù)器來定制緩存,如比較流行的redis緩存。我們需要實(shí)現(xiàn)MyBatis為我們提供的接口org.apache.ibatis.cache.Cache,緩存接口簡(jiǎn)介:
//獲取緩存編號(hào)
String getId();
//保存key值緩存對(duì)象
void putObject(Object key,Object value);
//通過key獲取緩存對(duì)象
Object getObject(Object key);
//通過key刪除緩存對(duì)象
Object removeObject(Object key);
//清空緩存
void clear();
//獲取緩存對(duì)象大小
int getSize();
//獲取緩存的讀寫鎖
ReadWriterLock getReadWriterLock();
由于每種緩存都有其不同的特點(diǎn),上面的接口都需要我們?nèi)?shí)現(xiàn)。假設(shè)我們已經(jīng)有一個(gè)實(shí)現(xiàn)類:cn.dintalk.MyCache。則配置如下:
完成上述配置,就能使用自定義的緩存了。MyBatis也支持在緩存中定義常用的屬性,如:
如果我們?cè)贛yCache這個(gè)類中增加setHost(String host) 方法,那么它在初始化的時(shí)候就會(huì)被調(diào)用,這樣我們可以對(duì)自定義的緩存設(shè)置一些外部參數(shù)。
Tips:?我們也可配置Sql層面的緩存規(guī)則,來決定它們是否需要刷新或使用緩存。
八:附錄-MyBatis常用配置及開發(fā)Tips
附錄1:mybatis-config.xml常用配置
附錄2:Mapper.xml頭約束
文末彩蛋
針對(duì)于上面所涉及到的知識(shí)點(diǎn)我總結(jié)出了有1到5年開發(fā)經(jīng)驗(yàn)的程序員在面試中涉及到的絕大部分架構(gòu)面試題及答案做成了文檔和架構(gòu)視頻資料免費(fèi)分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并發(fā)等架構(gòu)技術(shù)資料),希望能幫助到您面試前的復(fù)習(xí)且找到一個(gè)好的工作,也節(jié)省大家在網(wǎng)上搜索資料的時(shí)間來學(xué)習(xí),也可以關(guān)注我一下以后會(huì)有更多干貨分享。
資料獲取方式 QQ群搜索“708-701-457” 即可免費(fèi)領(lǐng)取
本文題目:那些你必須知道的MyBatis實(shí)用知識(shí)點(diǎn)
鏈接分享:http://www.ef60e0e.cn/article/gesoij.html