在JAVA發(fā)展過程中轧叽,涌現(xiàn)出一系列的ORM框架苗沧,JPA,Hibernate,Mybatis和Spring jdbc,本系列犹芹,將來研究Mybatis崎页。
通過研究mybatis源碼,可將mybatis的大致架構總結為下圖:
根據(jù)Mybatis源碼腰埂,將其抽象為三層:基礎支持層飒焦,核心處理層和接口層
基礎支持層包括:數(shù)據(jù)源、事務管理屿笼、日志牺荠、類型轉換、緩存驴一、Bind休雌、解析器等
核心處理層包括:配置解析、配置映射肝断、SQL解析杈曲、SQL執(zhí)行、結果集映射胸懈、插件等
接口層主要提供JAVA API
在本篇文章中担扑,將基于該框架圖,解決如下幾個問題:
Q1:結合代碼解析mybatis的CRUD原理是怎樣的趣钱?
Q2:為什么半自動化的Mybatis比自動化的Hibernate受歡迎涌献?
Q3:Mybatis為什么能實現(xiàn)松耦合?
一首有、mybatis的CRUD原理
小編分類整理了許多java進階學習材料和BAT面試題燕垃,需要資料的請加JAVA高階學習Q群:8515318105;就能領取2019年java架構師進階學習資料和BAT面試題井联。
為了解決該問題卜壕,我們先來看看如下代碼:
該代碼實現(xiàn)的功能是:根據(jù)user_id查詢用戶信息。 從代碼中烙常,我們可以看出印叁,大致分為:
讀取mybatis的全局配置文件mybatis-config.xml內(nèi)容
創(chuàng)建SqlSessionFactory會話工廠
根據(jù)SqlSessionFactory創(chuàng)建SQL會話SqlSession
執(zhí)行查詢操作
publicstaticvoidmain(String[]?args)throws?IOException{
//讀取配置文件內(nèi)容
String?resource?="demo/mybatis/resources/mybatis-config.xml";
InputStream?inputStream?=?Resources.getResourceAsStream(resource);
//創(chuàng)建SqlSessionFactory
SqlSessionFactory?sqlSF?=newSqlSessionFactoryBuilder().build(inputStream);
//創(chuàng)建SqlSession
SqlSession?sqlS?=?sqlSF.openSession();
//根據(jù)id查詢
try{
//查詢user_id=2的記錄
Listlist=?sqlS.selectList("getUserInfoById",2);
for(UserInfo?user?:list)?{
System.out.println("UserName:"+?user.getUser_name()?+",Addr:"+?user.getUser_addr());
}
}?finally?{
sqlS.close();
}
}
那么,我們再來看看军掂,Mybatis-config.xml內(nèi)容:
從內(nèi)容中,可以看出<configuration>下面有三個子節(jié)點,<properties>,<environment>和<mapper>節(jié)點昨悼。
那么蝗锥,這三個節(jié)點到底是表示什么呢?
1率触、properties節(jié)點表示屬性節(jié)點终议,可用于動態(tài)從外部獲取資源,將獲取的資源供上下文使用,我們來看看jdbc.properties內(nèi)容
#mysql
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db_test?characterEncoding=UTF-8
username=root
password=root
一看便知穴张,這是訪問數(shù)據(jù)庫相關參數(shù)细燎,那么哪個地方引用這些參數(shù)呢?<environment>子節(jié)點皂甘。
2玻驻、environment節(jié)點,環(huán)境節(jié)點配置節(jié)點偿枕,如用于配置數(shù)據(jù)庫測試環(huán)境璧瞬,開發(fā)環(huán)境等,很容易看出dataSource的相關子節(jié)點的占位符就引用了
properties節(jié)點從jdbc.properties獲取的內(nèi)容渐夸。
3嗤锉、mapper節(jié)點,即映射節(jié)點墓塌,用來鏈接映射文件瘟忱,我們來看看該映射文件內(nèi)容:
<?xml?version="1.0"?encoding="UTF-8"?>
PUBLIC?"-//mybatis.org//DTD?Mapper?3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--Query?all-->
SELECT?user_name?,user_addr?FROM?user_info
<!--Query?by?id-->
SELECT?user_name?,user_addr?FROM?user_info?WHERE?user_id=#{user_id}
<!--add-->
INSERT?INTO?user_info(user_name,user_addr)VALUES(#{user_name},#{user_addr})
<!--delete-->
DELETE?FROM?user_info?WHERE?user_id=#{user_id}
顯而易見,這就SQL的增刪改查苫幢。
通過如上分析访诱,我們在文章開始提出的三個問題,現(xiàn)在基本可以解決了态坦。
Q3:Mybatis為什么能實現(xiàn)松耦合?
從如上分析盐数,我們知道,使用mybatis作為ORM框架開發(fā)時伞梯,我們的SQL語句都寫在xml配置文件中(如上文的userInfo-config.xml)玫氢,從而解決了傳統(tǒng)硬編碼的強耦合問題,巧妙地實現(xiàn)了從“硬編碼”到“軟編碼”的過程谜诫。
除了松耦合的好處之外漾峡,有經(jīng)驗的開發(fā)人員應該清楚,硬編碼存在一個重大問題喻旷,即當改變SQL代碼后生逸,需要重新編譯、打包且预、部署等后槽袄,程序方可運行起來,而通過可配置化的xml方式實現(xiàn)的SQL語句锋谐,卻不需要遍尺。
Q4:為什么半自動化的Mybatis比自動化的Hibernate受歡迎?
從功能上講,Hibernate是非常強大的涮拗,但其有存在一些比較難以解決的問題:
學習成本大:對于新手乾戏,學習Hibernate的時間成本比Mybatis大很多迂苛,Mybatis很快就上手了
笨重:Hibernate強大的另一面,折射出其笨重的一面
封裝SQL:Hibernate封裝SQL鼓择,只向用戶提供API接口三幻,是造成其不靈活的根本因素
然而,mybatis卻將SQL獨立出來呐能,讓用戶自定義念搬。
通過如上對比,之所以說Hibernate自動化催跪,因為SQL生成锁蠕,解析,執(zhí)行等都是由Hibernate自動生成的懊蒸;
之所以說Mybatis半自動化荣倾,是因為SQL語句需要用戶自定義,SQL的解析骑丸,執(zhí)行等工作由Mybatis執(zhí)行舌仍。
可以這么說,傳統(tǒng)的jdbc是手工的通危,Hibernate是自動化的铸豁,而Mybati是基于jdbc和Hibernate的半自動化ORM框架。
二菊碟、完整Mybatis CRUD
小編分類整理了許多java進階學習材料和BAT面試題节芥,需要資料的請加JAVA高階學習Q群:8515318105;就能領取2019年java架構師進階學習資料和BAT面試題逆害。
創(chuàng)建Web Application項目
打開Intellij IDEA=>Create New Project=>Java Enterprise=>勾選 Web Application=>Next=>
給項目命名MybatisCRUD=>Finish
導入jar包
這里主要導入兩個jar包:MySQL驅動jar包和Mybatis jar包
Project Structure(Ctrl+Alt+Shift+S)=>Modules=>MybatisCRUD=>Dependencies=>選擇 JARS or directories…
成功導入后的結構如下:
創(chuàng)建測試數(shù)據(jù)
#創(chuàng)建數(shù)據(jù)庫
DROPDATABASEIFEXISTSdb_test
CREATEDATABASEdb_test
#創(chuàng)建數(shù)據(jù)表
DROPTABLEIFEXISTSUser_Info
CREATETABLEuser_info
(
user_idINT(5)?AUTO_INCREMENT?PRIMARYKEYNOTNULL,#用戶id
user_nameVARCHAR(50)NOTNULL,#用戶名
user_addrVARCHAR(100)NOTNULL#地址
)
#插入模擬數(shù)據(jù)
INSERTINTOuser_Info(user_name,user_addr)
VALUES('A','SH-PuDong'),('B','SH-YangPu'),
('C','SH-QingPu'),('D','SH-XuHui')
創(chuàng)建UserInfo實體
packagedemo.mybatis.entity;
publicclassUserInfo{
String?user_name;
String?user_addr;
publicStringgetUser_name(){
returnuser_name;
}
publicvoidsetUser_name(String?user_name){
this.user_name?=?user_name;
}
publicStringgetUser_addr(){
returnuser_addr;
}
publicvoidsetUser_addr(String?user_addr){
this.user_addr?=?user_addr;
}
}
創(chuàng)建三個資源文件
1.jdbc.property
#mysql
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db_test?characterEncoding=UTF-8
username=root
password=root
2.mybatis-config.xml
<?xml?version="1.0"?encoding="UTF-8"??>
PUBLIC?"-//mybatis.org//DTD?Config?3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--屬性-->
<!--環(huán)境-->
<!--映射-->
3.userInfo.config.xml
<?xml?version="1.0"?encoding="UTF-8"?>
PUBLIC?"-//mybatis.org//DTD?Mapper?3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--無條件查詢-->
SELECT?user_name?,user_addr?FROM?user_info
<!--通過id查詢-->
SELECT?user_name?,user_addr?FROM?user_info?WHERE?user_id=#{user_id}
<!--add-->
INSERT?INTO?user_info(user_name,user_addr)VALUES(#{user_name},#{user_addr})
<!--delete-->
DELETE?FROM?user_info?WHERE?user_id=#{user_id}
CRUD
1.查詢
packagedemo.mybatis.Test;
importdemo.mybatis.entity.UserInfo;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.List;
publicclassTestMybatis{
publicstaticvoidmain(String[]?args)throwsIOException{
//讀取配置文件內(nèi)容
String?resource?="demo/mybatis/resources/mybatis-config.xml";
InputStream?inputStream?=?Resources.getResourceAsStream(resource);
//創(chuàng)建SqlSessionFactory
SqlSessionFactory?sqlSF?=newSqlSessionFactoryBuilder().build(inputStream);
//創(chuàng)建SqlSession
SqlSession?sqlS?=?sqlSF.openSession();
//根據(jù)id查詢
try{
//查詢user_id=2的記錄
List?list?=?sqlS.selectList("getUserInfoById",2);
for(UserInfo?user?:?list)?{
System.out.println("UserName:"+?user.getUser_name()?+",Addr:"+?user.getUser_addr());
}
}finally{
sqlS.close();
}
}
}
2.添加
packagedemo.mybatis.Test;
importdemo.mybatis.entity.UserInfo;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.List;
publicclassTestMybatis{
publicstaticvoidmain(String[]?args)throwsIOException{
//讀取配置文件內(nèi)容
String?resource?="demo/mybatis/resources/mybatis-config.xml";
InputStream?inputStream?=?Resources.getResourceAsStream(resource);
//創(chuàng)建SqlSessionFactory
SqlSessionFactory?sqlSF?=newSqlSessionFactoryBuilder().build(inputStream);
//創(chuàng)建SqlSession
SqlSession?sqlS?=?sqlSF.openSession();
//添加數(shù)據(jù)
try{
UserInfo?addUser?=newUserInfo();
addUser.setUser_name("E");
addUser.setUser_addr("BJ-DongCheng");
sqlS.selectList("addUserInfo",addUser);
List?list=sqlS.selectList("listUserInfo");
for(UserInfo?user?:list){
System.out.println("UserName:"+user.getUser_name()+",Addr:"+user.getUser_addr());
}
}finally{
sqlS.close();
}
}
}
3.刪除
packagedemo.mybatis.Test;
importdemo.mybatis.entity.UserInfo;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.List;
publicclassTestMybatis{
publicstaticvoidmain(String[]?args)throwsIOException{
//讀取配置文件內(nèi)容
String?resource?="demo/mybatis/resources/mybatis-config.xml";
InputStream?inputStream?=?Resources.getResourceAsStream(resource);
//創(chuàng)建SqlSessionFactory
SqlSessionFactory?sqlSF?=newSqlSessionFactoryBuilder().build(inputStream);
//創(chuàng)建SqlSession
SqlSession?sqlS?=?sqlSF.openSession();
//刪除
try{
sqlS.selectList("delUserInfoById",12);
List?list=sqlS.selectList("listUserInfo");
for(UserInfo?user?:list){
System.out.println("UserName:"+user.getUser_name()+",Addr:"+user.getUser_addr());
}
}finally{
sqlS.close();
}
}
}
代碼目錄結構
小編分類整理了許多java進階學習材料和BAT面試題空免,需要資料的請加JAVA高階學習Q群:8515318105吓歇;就能領取2019年java架構師進階學習資料和BAT面試題望艺。