MyBatis框架簡介
什麼是MyBatis?
MyBatis是一個優秀的持久層框架(就是將某些資料持久化到硬碟或其他儲存器中的框架),它把jdbc對資料庫的操作進行了封裝,使使用者只需關注sql本身,不需要去執行jdbc的那一套複雜的操作。
MyBatis通過配置xml檔案或註解的方式,將statement或preparedstatement中的sql語句與java物件中的資料相互對映,最終生成可執行的sql語句,由MyBatis執行sql語句,並將返回結果封裝成java物件。
簡而言之,MyBatis封裝了JDBC對資料庫的複雜操作,並將返回結果封裝成所需的java物件。
MyBatis流程圖:
1.MyBatis-config.xml檔案是MyBatis的核心配置檔案,這個檔案中配置了執行環境,事務管理方式,是否使用連線池等,MyBatis可以通過該配置檔案建立SqlSessionFactory
2.SqlSessionFactory用來建立SqlSession
3.SqlSession是用來發送sql語句到資料庫執行,並返回結果,類似於jdbc中的connection
4.executor是MyBatis的一個底層物件,用於執行sql語句
5.MapperStatement也是MyBatis的一個底層物件,用於將配置檔案中的sql語句對映為可執行的sql語句。
JDBC與MyBatis的對比
JDBC:
1.使用jdbc有大量重複且複雜的程式碼
2.jdbc中的sql語句是寫死在程式碼中,一旦修改sql還需重新編譯程式碼
3.jdbc本身是不支援使用連線池的,會不斷的建立連線,釋放資源,影響效率
4.jdbc返回的ResultSet物件,需要我們手動處理,特別麻煩
MyBatis:
1.MyBatis對JDBC進行了封裝,可以簡化了程式碼
2.MyBatis的sql語句都是寫在配置檔案中的,如需修改sql,修改配置檔案即可
3.MyBatis本身是支援連線池的,且MyBatis還可以相容其他連線池
4.MyBatis會將返回的結果,封裝為相應的java物件,極大的減少了我們的麻煩。
MyBatis的用法
1.首先匯入MyBatis框架的所需依賴
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
2.配置MyBatis的核心配置檔案,MyBatis-config.xml
1)配置標頭檔案
<?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"> <!-- MyBatis的全域性配置檔案 --> <configuration > </configuration>
第一行是xml文件的宣告,及使用的編碼
第2,3,4行用來引入xml檔案的約束文件,該文件受mybatis-3-config.dtd的約束
mybatis的環境配置都是在configuration中進行配置的。
2)配置MyBatis的常用配置
<?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">
<!-- MyBatis的全域性配置檔案 -->
<configuration >
<environments default="develop">
<environment id="develop">
<!--配置事務管理方式,MANAGED/JDBC
MANAGED:自己管理
JDBC:由JDBC進行管理(推薦)
-->
<transactionManager type="JDBC"></transactionManager>
<!--配置資料庫連線方式,POOLED/UNPOOLED/JNDI
JNDI:已過時
UNPOOLED:不使用連線池
POOLED:使用連線池
-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/yonghedb?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper>
<mapper resource="EmpMapper.xml"/>
</mapper>
</mappers>
</configuration>
environments,mybatis中可以同時部署多套環境,都是配置在environments,通過environments標籤中的default屬性來切換環境。
environment,mybatis中的環境配置,每個environment都有一個id,environments通過這個id來切換環境
transactionManager,資料庫事務管理方式,由MANAGED/JDBC兩種,MANAGED,自己手動管理事務,JDBC,由jdbc來管理事務
datasource,資料來源,這裡配置資料庫連線是否使用連線池,JNDI/POOLED/UNPOOLED
mappers,可以在該標籤下配置多個mapper
mapper,每個mapper對應一個mapper.xml配置檔案
3.建立對應表的mapper.xml檔案,並將該對映檔案配置到MyBatis-config.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值應該保證唯一
在程式中通過[ namespace + id ]定位到要執行哪一條SQL語句
-->
<mapper namespace="EmpMapper">
<!-- 通過select、insert、update、delete標籤宣告要執行的SQL -->
<!-- 練習1: 查詢emp表中的所有員工資訊
resultType指定查詢的結果將會封裝到什麼型別中
即使最終返回的結果是集合(List<Emp>),resultType也只需要指定集合中的泛型即可!
-->
<select id="findAll" resultType="com.tedu.pojo.Emp">
select * from emp
</select>
</mapper>
mapper,根標籤,其中namespace(名稱空間,要求不能重複),通過namespace+id來定位一條sql語句
select,對映檔案中配置的sql型別標籤
id,一條sql語句的標識
resultType,sql執行返回的結果型別,如果返回的是一個集合,那麼這裡包含的應該是集合的泛型,例如上述sql返回結果為list
則這裡resultType就是泛型emp的全限定類名
resultMap,複雜物件結構,常用與多表查詢,resultType與resultMap不能同時使用
4.通過Java程式碼查詢資料庫中資料
public class TestMyBatis(){
public void main(String args[]){
//1.讀取MyBatis-config.xml核心配置檔案
InputStream in=Resources.getResourceAsStream("mybatis-config.xml");
//2.建立SqlSessionFactory物件
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
//3.建立Sqlsession物件
SqlSession sqlSession=sqlSessionFactory.openSession();
//4.執行sql語句
List<emp> empList = sqlSession.selectList("emp.findAll");
//5.對返回結果進行操作
for (emp item:empList) {
System.out.println(item.toString());
}
}
}
MyBatis中的佔位符#{}和${}
${}和#{}的區別:
‘#{}’相當與jdbc中的?,並會將傳進來的字元進行轉義處理,在字元的兩邊加上單引號。
‘${}’是直接將傳進來的字元拼接到sql中的,因此有可能出現sql注入,所以每個${}傳進來的值,都需進行封裝,即使只有一個值。
動態sql標籤
標籤'
<!--
* 如果沒有引數, 則不執行where子句, 預設查詢所有員工:
* select * from emp
* 如果引數中只有minSal(即minSal不為null), 則:
* ... where salary > minSal
* 如果引數中只有maxSal(即maxSal不為null), 則:
* ... where salary < maxSal
* 如果引數有 minSal、maxSal(即minSal、maxSal不為null), 則:
* ... where salary > minSal and salary < maxSal -->
<select id="findAllBySal" resultType="com.tedu.pojo.Emp">
select * from emp
where 1=1
<if test="minSal != null">
and salary>#{minSal}
</if>
<if test="maxSal != null">
and salary <![CDATA[ < ]]> #{maxSal}
</if>
</select>
根據if標籤中的test屬性,來判斷是否拼接if標籤中的sql
注意sql中的 'where 1==1',這是為了防止第一個if中的and
標籤'
<!--
* 如果沒有引數, 則不執行where子句, 預設查詢所有員工:
* select * from emp
* 如果引數中只有minSal(即minSal不為null), 則:
* ... where salary > minSal
* 如果引數中只有maxSal(即maxSal不為null), 則:
* ... where salary < maxSal
* 如果引數有 minSal、maxSal(即minSal、maxSal不為null), 則:
* ... where salary > minSal and salary < maxSal -->
<select id="findAllBySal2" resultType="com.tedu.pojo.Emp">
select * from emp
<where>
<if test="minSal != null">
and salary>#{minSal}
</if>
<if test="maxSal != null">
and salary <![CDATA[ < ]]> #{maxSal}
</if>
</where>
</select>
where標籤會在需要的時候生成where語句,並且會剔除多餘的and或or,例如本例中若第一個if成立就會生成where並剔除and
標籤'
這個標籤主要用於遍歷集合
<!--
delete from emp where id in (1,3,5,7)
collection: 如果傳的引數僅僅是一個數組或者List集合, collection可以指定為
array或list; 如果傳的是多個引數,用map封裝,collection則指定為map中的key
open: 指定生成的SQL片段以什麼符號開始
close: 指定生成的SQL片段以什麼符號結束
item: 指定變數接收陣列或集合中的元素
separator: 指定一個間隔符, 在將陣列或集合中的每個元素拼接到SQL片段之後,
在後面拼接一個間隔符
-->
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="array" open="(" item="id" separator="," close=")">
#{id}
</foreach>
</delete>
foreach標籤中的屬性
collection 集合(必需)
item 集合中的元素(必需)
open 以什麼開始
close 以什麼結束
separator 集合中元素的分割符
MyBatis的介面開發
上述,在Java程式碼中查詢資料庫時,是通過namepace+id定位sql的,mybatis還有一個更簡單的方法來定位sql,通過介面中的方法直接定位到sql
要求:
1.建立一個介面,再建立mapper對映檔案,對映檔案中的namespace與介面的全限定類名一致
2.mapper對映檔案中的每條sql,介面中都需要有一個對應的方法
3.介面中方法的入參型別要與sql中接收的引數型別一致
4.介面中方法的返回值型別要與sql中resultType中的一致(注意resutType中只是泛型)