博客遷移至:https://blog.csdn.net/wangshihuidev
前言
主要內(nèi)容如下:
內(nèi)容來自于《Java EE 企業(yè)級(jí)應(yīng)用開發(fā)教程》這本書的翻讀筆記远搪,內(nèi)容相對(duì)簡(jiǎn)單,用于基礎(chǔ)知識(shí)的復(fù)習(xí)鞏固逢捺。
MyBatis的工作流程
MyBatis框架在操作數(shù)據(jù)庫時(shí)谁鳍,大體經(jīng)過了8個(gè)步驟。下面就對(duì)圖6-4中的每一步流程進(jìn)行詳細(xì)講解劫瞳,具體如下倘潜。
(1)讀取MyBatis配置文件mybatis-config.xml。mybatis-config.xml作為MyBatis的全局配置文件柠新,配置了MyBatis的運(yùn)行環(huán)境等信息窍荧,其中主要內(nèi)容是獲取數(shù)據(jù)庫連接。
(2)加載映射文件Mapper.xml恨憎。Mapper.xml文件即SQL映射文件蕊退,該文件中配置了操作數(shù)據(jù)庫的SQL語句,需要在mybatis-config.xml中加載才能執(zhí)行憔恳。mybatis-config.xml可以加載多個(gè)配置文件瓤荔,每個(gè)配置文件對(duì)應(yīng)數(shù)據(jù)庫中的一張表。
(3)構(gòu)建會(huì)話工廠钥组。通過MyBatis的環(huán)境等配置信息構(gòu)建會(huì)話工廠SqlSessionFactory输硝。
(4)創(chuàng)建SqlSession對(duì)象。由會(huì)話工廠創(chuàng)建SqlSession對(duì)象程梦,該對(duì)象中包含了執(zhí)行SQL的所有方法点把。
(5)MyBatis底層定義了一個(gè)Executor接口來操作數(shù)據(jù)庫,它會(huì)根據(jù)SqlSession傳遞的參數(shù)動(dòng)態(tài)地生成需要執(zhí)行的SQL語句屿附,同時(shí)負(fù)責(zé)查詢緩存的維護(hù)郎逃。
(6)在Executor接口的執(zhí)行方法中,包含一個(gè)MappedStatement類型的參數(shù)挺份,該參數(shù)是對(duì)映射信息的封裝褒翰,用于存儲(chǔ)要映射的SQL語句的id、參數(shù)等。Mapper.xml文件中一個(gè)SQL對(duì)應(yīng)一個(gè)MappedStatement對(duì)象优训,SQL的id即是MappedStatement的id朵你。
(7)輸入?yún)?shù)映射。在執(zhí)行方法時(shí)揣非,MappedStatement對(duì)象會(huì)對(duì)用戶執(zhí)行SQL語句的輸入?yún)?shù)進(jìn)行定義(可以定義為Map抡医、List類型、基本類型和POJO類型), Executor執(zhí)行器會(huì)通過MappedStatement對(duì)象在執(zhí)行SQL前妆兑,將輸入的Java對(duì)象映射到SQL語句中魂拦。這里對(duì)輸入?yún)?shù)的映射過程就類似于JDBC編程中對(duì)preparedStatement對(duì)象設(shè)置參數(shù)的過程。
(8)輸出結(jié)果映射搁嗓。在數(shù)據(jù)庫中執(zhí)行完SQL語句后,MappedStatement對(duì)象會(huì)對(duì)SQL執(zhí)行輸出的結(jié)果進(jìn)行定義(可以定義為Map和List類型箱靴、基本類型腺逛、POJO類型), Executor執(zhí)行器會(huì)通過MappedStatement對(duì)象在執(zhí)行SQL語句后,將輸出結(jié)果映射至Java對(duì)象中衡怀。這種將輸出結(jié)果映射到Java對(duì)象的過程就類似于JDBC編程中對(duì)結(jié)果的解析處理過程棍矛。
MyBatis的核心對(duì)象
在使用MyBatis框架時(shí),主要涉及兩個(gè)核心對(duì)象:
- SqlSessionFactory
- SqlSession
SqlSessionFactory
SqlSessionFactory是MyBatis框架中十分重要的對(duì)象抛杨,它是單個(gè)數(shù)據(jù)庫映射關(guān)系經(jīng)過編譯后的內(nèi)存鏡像够委,其主要作用是創(chuàng)建SqlSession。SqlSessionFactory對(duì)象的實(shí)例可以通過SqlSessionFactoryBuilder對(duì)象來構(gòu)建怖现,而SqlSessionFactoryBuilder則可以通過XML配置文件或一個(gè)預(yù)先定義好的Configuration實(shí)例構(gòu)建出SqlSessionFactory的實(shí)例
SqlSessionFactory對(duì)象是線程安全的茁帽,它一旦被創(chuàng)建,在整個(gè)應(yīng)用執(zhí)行期間都會(huì)存在屈嗤。如果我們多次地創(chuàng)建同一個(gè)數(shù)據(jù)庫的SqlSessionFactory潘拨,那么此數(shù)據(jù)庫的資源將很容易被耗盡。為了解決此問題饶号,通常每一個(gè)數(shù)據(jù)庫都會(huì)只對(duì)應(yīng)一個(gè)SqlSessionFactory铁追,所以在構(gòu)建SqlSessionFactory實(shí)例時(shí),建議使用單列模式茫船。
SqlSession
SqlSession是MyBatis框架中另一個(gè)重要的對(duì)象琅束,它是應(yīng)用程序與持久層之間執(zhí)行交互操作的一個(gè)單線程對(duì)象,其主要作用是執(zhí)行持久化操作算谈。SqlSession對(duì)象包含了數(shù)據(jù)庫中所有執(zhí)行SQL操作的方法涩禀,由于其底層封裝了JDBC連接,所以可以直接使用其實(shí)例來執(zhí)行已映射的SQL語句濒生。每一個(gè)線程都應(yīng)該有一個(gè)自己的SqlSession實(shí)例埋泵,并且該實(shí)例是不能被共享的。同時(shí),SqlSession實(shí)例也是線程不安全的丽声,因此其使用范圍最好在一次請(qǐng)求或一個(gè)方法中礁蔗,絕不能將其放在一個(gè)類的靜態(tài)字段、實(shí)例字段或任何類型的管理范圍(如Servlet的HttpSession)中使用雁社。使用完SqlSession對(duì)象之后浴井,要及時(shí)地關(guān)閉它,通趁鼓欤可以將其放在finally塊中關(guān)閉
MyBatis 配置文件
configuration
在MyBatis框架的核心配置文件中磺浙,<configuration>元素是配置文件的根元素,其他元素都要在<configuration>元素內(nèi)配置徒坡。
properties
<properties>是一個(gè)配置屬性的元素撕氧,該元素通常用于將內(nèi)部的配置外在化,即通過外部的配置來動(dòng)態(tài)地替換內(nèi)部定義的屬性喇完。例如伦泥,數(shù)據(jù)庫的連接等屬性,就可以通過典型的Java屬性文件中的配置來替換锦溪,具體方式如下不脯。
在項(xiàng)目的src目錄下,添加一個(gè)全名為db.properties的配置文件刻诊,編輯后的代碼如下所示防楷。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
在MyBatis配置文件mybatis-config.xml中配置<properties... />屬性,具體如下则涯。
<properties resource="db.properties" />
修改配置文件中數(shù)據(jù)庫連接的信息复局,具體如下。
<dataSource type="POOLED">
<! -- 數(shù)據(jù)庫驅(qū)動(dòng) -->
<property name="driver" value="${jdbc.driver}" />
<! -- 連接數(shù)據(jù)庫的url -->
<property name="url" value="${jdbc.url}" />
<! -- 連接數(shù)據(jù)庫的用戶名 -->
<property name="username" value="${jdbc.username}" />
<! -- 連接數(shù)據(jù)庫的密碼 -->
<property name="password" value="${jdbc.password}" />
</dataSource>
完成上述配置后是整,dataSource中連接數(shù)據(jù)庫的4個(gè)屬性(driver肖揣、url、username和password)值將會(huì)由db.properties文件中對(duì)應(yīng)的值來動(dòng)態(tài)替換浮入。這樣就為配置提供了諸多靈活的選擇龙优。
settings
<settings>元素主要用于改變MyBatis運(yùn)行時(shí)的行為,例如開啟二級(jí)緩存事秀、開啟延遲加載等彤断。雖然不配置<settings>元素,也可以正常運(yùn)行MyBatis易迹,但是熟悉<settings>的配置內(nèi)容以及它們的作用還是十分必要的宰衙。<settings>元素中的常見配置及其描述如表所示。
typeAliases
<typeAliases>元素用于為配置文件中的Java類型設(shè)置一個(gè)簡(jiǎn)短的名字睹欲,即設(shè)置別名供炼。別名的設(shè)置與XML配置相關(guān)一屋,其使用的意義在于減少全限定類名的冗余。
使用<typeAliases>元素配置別名的方法如下袋哼。
<! -- 定義別名 -->
<typeAliases>
<typeAlias alias="user" type="com.itheima.po.User"/>
</typeAliases>
上述示例中冀墨,<typeAliases>元素的子元素<typeAlias>中的type屬性用于指定需要被定義別名的類的全限定名;alias屬性的屬性值user就是自定義的別名涛贯,它可以代替com.itheima. po.User使用在MyBatis文件的任何位置诽嘉。如果省略alias屬性,MyBatis會(huì)默認(rèn)將類名首字母小寫后的名稱作為別名弟翘。
當(dāng)POJO類過多時(shí)虫腋,還可以通過自動(dòng)掃描包的形式自定義別名,具體示例如下稀余。
<! -- 使用自動(dòng)掃描包來定義別名 -->
<typeAliases>
<package name="com.itheima.po"/>
</typeAliases>
上述示例中悦冀,<typeAliases>元素的子元素<package>中的name屬性用于指定要被定義別名的包,MyBatis會(huì)將所有com.itheima.po包中的POJO類以首字母小寫的非限定類名來作為它的別名睛琳,比如com.itheima.po.User的別名為user, com.itheima.po.Customer的別名為customer等雏门。
除了可以使用<typeAliases>元素自定義別名外,MyBatis框架還默認(rèn)為許多常見的Java類型(如數(shù)值掸掏、字符串、日期和集合等)提供了相應(yīng)的類型別名宙帝,如表所示丧凤。
typeHandler
MyBatis在預(yù)處理語句(PreparedStatement)中設(shè)置一個(gè)參數(shù)或者從結(jié)果集(ResultSet)中取出一個(gè)值時(shí),都會(huì)用其框架內(nèi)部注冊(cè)了的typeHandler(類型處理器)進(jìn)行相關(guān)處理步脓。typeHandler的作用就是將預(yù)處理語句中傳入的參數(shù)從javaType(Java類型)轉(zhuǎn)換為jdbcType(JDBC類型)愿待,或者從數(shù)據(jù)庫取出結(jié)果時(shí)將jdbcType轉(zhuǎn)換為javaType。
為了方便轉(zhuǎn)換靴患,MyBatis框架提供了一些默認(rèn)的類型處理器仍侥,其常用的類型處理器如表所示。
Mybatis 映射文件
如何返回Mysql主鍵ID
執(zhí)行插入操作后鸳君,很多時(shí)候我們會(huì)需要返回插入成功的數(shù)據(jù)生成的主鍵值农渊,此時(shí)就可以通過如下3個(gè)屬性來實(shí)現(xiàn)。
如果使用的數(shù)據(jù)庫支持主鍵自動(dòng)增長(如MySQL)或颊,那么可以通過keyProperty屬性指定PO類的某個(gè)屬性接收主鍵返回值(通常會(huì)設(shè)置到id屬性上)砸紊,然后將useGeneratedKeys的屬性值設(shè)置為true,其使用示例如下囱挑。
<insert id="addCustomer"
parameterType="com.itheima.po.Customer"
keyProperty="id" useGeneratedKeys="true" >
insert into t_customer(username, jobs, phone)
values(#{username}, #{jobs}, #{phone})
</insert>
使用上述配置執(zhí)行插入后醉顽,會(huì)返回插入成功的行數(shù),以及插入行的主鍵值平挑。
注意:成功的行數(shù)通過返回值返回游添,主鍵ID通過PO類設(shè)置的字段返回系草。
為了驗(yàn)證此配置,可以通過如下代碼測(cè)試唆涝。
@Test public void addCustomerTest(){
// 獲取SqlSession
SqlSession sqlSession = MybatisUtils.getSession();
Customer customer = new Customer();
customer.setUsername("rose");
customer.setJobs("student");
customer.setPhone("13333533092");
int rows = sqlSession.insert("com.itheima.mapper."+"CustomerMapper.addCustomer", customer);
// 輸出插入數(shù)據(jù)的主鍵id值
System.out.println(customer.getId());
if(rows > 0){
System.out.println("您成功插入了"+rows+"條數(shù)據(jù)找都!");
}else{
System.out.println("執(zhí)行插入操作失敗石抡!! ! ");
}
sqlSession.commit();
sqlSession.close();
}
執(zhí)行程序后檐嚣,控制臺(tái)的輸出結(jié)果如圖所示。