第一個Mybatis程式示例 Mybatis簡介(一)
在JDBC小結中(可以參閱本人JDBC系列文章),介紹到了ORM,其中Mybatis就是一個不錯的ORM框架
MyBatis由iBatis演化而來
iBATIS一詞來源於“internet”和“abatis”的組合,是一個由Clinton Begin在2001年發起的開放原始碼專案。於2010年6月16號被谷歌託管,改名為MyBatis。
是一個基於SQL對映支援Java和·NET的持久層框架。
MyBatis是一個優秀的持久層框架,對JDBC操作資料庫進行了封裝,封裝後的Mybatis使應用程式開發者只需要關注SQL本身
完全不需要再次花精力去處理例如註冊驅動、建立connection、建立statement、手動設定引數、結果集檢索等jdbc繁雜的過程程式碼(最初的Mybatis環境搭建只需要立項之初配置即可)
- 要求通過xml或註解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來
- 並通過java物件和statement中的sql進行對映生成最終執行的sql語句
- mybatis框架執行sql並將結果對映成java物件並返回。
專案環境搭建好之後我們需要做的就是通過XML或者註解將要執行的SQL配置起來,也就是僅僅關注SQL
中文版文件
http://www.mybatis.org/mybatis-3/zh/index.html
github地址
https://github.com/mybatis/mybatis-3
截止本文,最新版本為:mybatis-3.4.6
本文不涉及架構解析,首先演示了一個最簡單的示例,然後以這個簡單示例為基礎,簡單介紹了從外部看過去的Mybatis的呈現樣子
幫助簡單瞭解Mybatis
第一個Mybatis程式
1.新建專案
新建一個Java 專案
我取名為mybatis,並且新建了一個包 first
2.包獲取與匯入
基礎的兩個包
mybatis 和 mysql-connector(因為要用MYSQL) ,可以從官方下載
https://dev.mysql.com/downloads/connector/j/
https://github.com/mybatis/mybatis-3/releases
3.資料庫準備
本人已經有本地資料庫,MYSQL,以student表為測試
CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '預設姓名' COMMENT '姓名', `age` int(11) DEFAULT '1', `sex` varchar(255) DEFAULT NULL, `random` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDBDEFAULT CHARSET=utf8;
資料庫資訊為:
String user = "root";
String password = "123456";
String url = "jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8";
4.配置檔案設定
src下新建config,然後新建xml檔名為mybatis-config.xml
內容從官方文件中複製: http://www.mybatis.org/mybatis-3/zh/getting-started.html
如下圖所示官方示例的配置XML
5.SQL對映檔案設定
src下新建mapper資料夾,建立xml檔名為myBatis.xml
內容從官方文件複製
6.調整配置檔案
主要任務就是將資料庫連結資訊設定準確,並且將SQL對映檔案的位置設定準確
對於url的設定需要注意“&”符號,在xml的配置檔案中 要用 & 代替&
這是XML的語法本身的問題與mybatis沒關係
五個在XML文件中預定義好的實體:
< < 小於號
> > 大於號
& & 和
' ' 單引號
" " 雙引號
實體必須以符號"&"開頭,以符號";"結尾
7.建立實體類Student
8.修改myMapper.xml檔案
需要調整namespace 設定resultType型別,需要設定使用的sql
9.測試
每一次的業務開發時,其實需要的僅僅是編寫myMapper.xml檔案,然後對其呼叫
環境配置等工作環境搭建之初就已經完成了
初識Mybatis
在第一個Mybatis程式示例中的程式碼幾乎都是官方文件中的,根據官方的提示一步一步操作即可建立
不管是Mybatis還是JDBC還是其他,終歸是需要連線資料庫的,不管以何種形式,連線以後就是需要執行SQL,所以你還得準備好你想要執行的SQL
在Mybatis中,SQL以XML檔案的形式設定 ,也就是上例中的myMapper.xml檔案
所以在上例中的主配置檔案mybatis-config.xml中我們配置了資料庫的連線資訊以及SQL XML檔案的位置
每個基於Mybatis的應用都是以一個SqlSessionFactory的例項為中心的,這一部分核心的配置檔案就是提供給SqlSessionFactory例項的。
既然是操作資料庫,很重要的一部分自然是SQL語句
mapper檔案的格式是什麼?對於一個SQL到底是查詢還是delete?返回型別是什麼?如下圖所示,我們的型別是first.Student,SQL的內容又是什麼?
此處不深入,但是很顯然,對於Mybatis mapper對映檔案的編寫是很重要的一部分學習內容
有了核心配置檔案就可以構建SqlSessionFactory例項,通過SqlSessionFactory例項就可以獲取到SqlSession物件
SqlSession是Mybatis最重要的構建之一,可以簡單的認為Mybatis一系列的配置目的是生成類似 JDBC生成的Connection物件的SqlSession物件
有了這個“Connection”物件之後才能進一步與資料庫進行交流
這個“Connection”物件就可以根據我們mapper xml配置檔案中設定的識別符號,比如上例中的selectStudent的全名,以及引數執行SQL
如上圖所示,我們從頭簡單的理一下Mybatis的基本流程
需要兩個重要資訊:資料庫配置以及mapper檔案位置
通過這兩個核心資訊可以生成SqlSessionFactory,通過SqlSessionFactory就可以建立SqlSession
SqlSession就可以根據名稱識別符號識別需要執行哪個檔案裡面的哪個SQL,比如上面就是執行mapper/myMapper.xml檔案中,識別符號為selectStudent的那一條
而執行該SQL以及周邊的資訊,都在檔案中指定了,比如SQL內容是什麼?返回型別又是什麼?
通過配置檔案到SqlSessionFactory例項的建立,完成了巨集觀上Mybatis的配置,兩個主要任務:
- 要從哪個資料庫進行操作?
- 要操作的SQL在哪裡?
通過SqlSession完成了具體一次執行的任務
- 執行哪個SQL?通過層級的命名識別符號定位
- 執行SQL的細節資訊有哪些?SQL內容,引數內容,返回型別等
比如現在的中國好聲音,形式變化了
所有的參賽選手在等待大廳內坐等,所有的人的姓名和演唱曲目形成了歌單,導師點歌的形式選擇選手錶演。
這個過程很類似Mybatis的處理
所有的選手形成了一個等待集合,這就相當於是一系列的mapper.xml檔案,每個選手都有一個名字,這就相當於是一個檔案(一個檔名,或者說一個名稱空間)
但是重名的有很多,當導師叫名字 xxx 的時候,其實是在說“本次參加中國好聲音,等待大廳的xxx”,但是不說大家也都知道,說王偉的時候,肯定不會是你身邊坐著那個同事
但是程式不知道,這個“本次參加中國好聲音,等待大廳的xxx”就相當於上例中namespace="mapper.myMapper"
整個節目組,導師,時間,場地等這些環境資訊因素構成了整個的節目核心,這些零散的資料就是配置專案
構成的整體就相當於一個執行的機器,這就相當於SqlSessionFactory
他作為核心知道整個節目組所有的資訊,導師的資訊等等,學員以及學員表演曲目也呈現在了導師面前
當一個導師進行點歌時,就類似SqlSession執行一次資料庫操作
導師通過姓名,也就是我們上面說的“一個隱含的名稱空間”,進行點歌,選擇選手進行表演
這就相當於從等候大廳定位了一個Mapper檔案,而他表演的那個曲目就好像是mapper檔案中的ID,因為你唱了《止戰之殤》,別人也可以再唱一次。
而針對於歌曲自身的更多資訊,自然要看你接下來的表演了,是不是改變了?變化了哪些內容等等,這都屬於某一個id對應的mapper檔案中的具體內容資訊。
Mybatis核心為配置以及對映
- 配置資訊搭建了Mybatis應用框架
- 對映設定了一次執行的所需資訊
Mybatis細化實現為核心的協調 組裝
核心資訊包含了將要執行的目標資料庫資訊以及需要執行的SQL對映,有了這兩部分資訊如果是在Navicat等客戶端的話就足夠了,使用資料庫資訊連線,然後執行SQL
對於Mybatis也是足夠了,不過程式碼中畢竟不是可以手動連線資料庫,手動輸入SQL,肉眼檢視結果這麼簡單
所以還有很多的周邊業務需要處理,比如配置檔案如何表示?都有哪些屬性需要配置?另外MyBatis是一個功能強大的工具,所以還提供了更多的細節調優引數以供設定
對於mapper檔案的位置如何描述?
前面示例中使用了上面的形式,另外你也可以指定一個包,比如 下面的形式,那麼這個包下面所有的xml都會被掃描,相當於你全部都羅列了出來
<mappers> <package name="org.mybatis.builder"/> </mappers>
對於對映如何表述?可以使用XML也還可以使用註解的形式
他們又有哪些語法?每種形式的利弊是什麼?欄位屬性都有哪些?
引數如何設定? 返回結果又是如何設定呢?等等
儘管這一系列的實現都很複雜,但是,仍舊是圍繞著核心資訊來的
所以對於Mybatis的學習,最開始應該瞭解整體的處理過程,瞭解各塊
然後就是深入學習配置檔案以及對映的設定配置
最後就是了解原始碼的架構
如果還有精力,最好的文件就是原始碼了
附錄:完整程式碼
資料庫
CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '預設姓名' COMMENT '姓名', `age` int(11) DEFAULT '1', `sex` varchar(255) DEFAULT NULL, `random` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
專案結構
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/myMapper.xml"/> </mappers> </configuration>
myMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mapper.myMapper"> <select id="selectStudent" resultType="first.Student"> select * from student where id = #{id} </select> </mapper>
Student
package first; public class Student { private Long id; private String name; private Integer age; private String sex; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { final StringBuilder sb = new StringBuilder("Student{"); sb.append("id=").append(id); sb.append(", name='").append(name).append('\''); sb.append(", age=").append(age); sb.append(", sex='").append(sex).append('\''); sb.append('}'); return sb.toString(); } }
測試程式碼
package first; 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 Test { public static void main(String[] args) throws Exception { /* * 每個基於 MyBatis 的應用都是以一個 SqlSessionFactory 的例項為中心的。 * SqlSessionFactory 的例項可以通過 SqlSessionFactoryBuilder 獲得。 * 而 SqlSessionFactoryBuilder 則可以從 XML 配置檔案或一個預先定製的 Configuration 的例項構建出 SqlSessionFactory 的例項。 * */ String resource = "config/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); /* * 從 SqlSessionFactory 中獲取 SqlSession * */ SqlSession session = sqlSessionFactory.openSession(); try { Student student = (Student) session.selectOne("mapper.myMapper.selectStudent", 2); System.out.println(student); } finally { session.close(); } } }
介面應用
而對於SQL的執行更好的一種方式是使用介面,而不是直接通過字串去定位需要執行的目標資源
藉助於介面不是基於字串常量的,就會更安全,而且使用介面邏輯概念更加清晰
在原有結構上增加一個介面和一個對映檔案
MyMapper.java
package first; public interface MyMapper { Student selectStudent(Integer id); }
myMapper2.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="first.MyMapper"> <select id="selectStudent" resultType="first.Student"> select * from student where id = #{id} </select> </mapper>
從下圖可以看得出來介面與XML對映的資料對照關係,XML對映檔案的namespace需要與介面的全限定名對應
介面的方法名對應XML對映的id
介面方法返回型別為XML對映的ResultMap(resultType)
介面方法的引數對應XML對映的入參
新增加了一個XML對映檔案,需要將路徑新增到配置中
增加一個測試類
package first; 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 Test2 { public static void main(String[] args) throws Exception { /* * 每個基於 MyBatis 的應用都是以一個 SqlSessionFactory 的例項為中心的。 * SqlSessionFactory 的例項可以通過 SqlSessionFactoryBuilder 獲得。 * 而 SqlSessionFactoryBuilder 則可以從 XML 配置檔案或一個預先定製的 Configuration 的例項構建出 SqlSessionFactory 的例項。 * */ String resource = "config/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"development"); /* * 從 SqlSessionFactory 中獲取 SqlSession * */ SqlSession session = sqlSessionFactory.openSession(); try { MyMapper mapper = session.getMapper(MyMapper.class); Student student = mapper.selectStudent(2); System.out.println(student); } finally { session.close(); } } }
關鍵程式碼為
MyMapper mapper = session.getMapper(MyMapper.class); Student student = mapper.selectStudent(2);
結果與前面一致