myBatis 入門學習
0.1 框架和工具類
-
工具類
-
對程式中一小段程式碼的封裝。專案中大多數程式碼還是需要我們寫。
-
-
框架
-
通俗理解框架
-
可以看做一個半成品的軟體/專案。使用框架開發專案,專案中半數以上程式碼就不需要 我們編寫了。
-
我們一般需要配置(大多數框架都是重配置輕編碼的)+少量編碼,就可完成專案中的需求。
-
框架的目的 就是為了簡化編碼:
eg:Mybatis
。我們在學習完Mybatis
之後,dao
層會更簡單。你只需要寫一個dao
介面,然後寫一個SQL
語句,dao
層就已經寫完了。
-
-
學習步驟
-
這個框架能幹什麼?
-
導包+配置
-
框架少量的
API
-
0.2ORM
-
Object Relational Mapping
物件關係對映的思想 -
物件 - Java中的物件 關係-關係型資料庫中表的記錄 對映 - 一對一關聯起來
-
java
專案中的每一個實體類,對應資料庫中的一個表;java
類中的屬性,對應資料庫表中的欄位。java
類中的一個實體物件,對應一個數據表中的一條記錄 -
全自動
ORM
框架:hibernate
。通過操作實體物件,就可以完成對資料庫表中記錄的操作。複雜業務效能低下,不可定製,學習成本高。
-
半自動的
ORM
框架:Mybatis
,ibatis
基於
ORM
,但是SQL
語句需要我們自己編寫。自己優化SQL
,可定製性強,效率高。
0.3Mybatis
&原生JDBC
-
原生jdbc
-
註冊驅動,設定連線引數 -
獲取連線 -
獲取執行物件
-
設定
SQL
引數並執行SQL
語句 -
封裝結果集並封裝成實體物件
-
釋放資源
相同的內容已經抽取到工具類中(上述刪除線標識的步驟)
模板化(步驟不變,部分步驟相同,上述加粗的內容)的操作,也是可以抽取封裝的。
但是相同的步驟中又有不同的地方,不同的地方如果也要實現解耦,需要通過配置來實現
-
-
Mybatis
解決方案-
連線複用:使用資料庫連線池初始化並管理連線
-
解耦:將
SQL
語句和設定到SQL
中的引數抽取到xml
配置檔案中 -
自動封裝:通過反射內省等技術,實現查詢結果集欄位
-
-
Mybatis
框架抽取後的樣子
-
Mybatis
簡介-
是一個數據持久層(
DAO
)框架,封裝共性內容讓使用者只關注SQL
本身。結合了ORM
思想,是一個ORM
半自動的框架。 -
使用
Mybatis
之後,我們只需要定義一個Dao
層介面+儲存SQL
的配置檔案(Mybatis
對映配置檔案),就可以完成Dao
層內容。
-
1.Mybatis
快速入門
1.1Mybatis
快速入門步驟
-
匯入Jar包
-
mybatis-3.5.3.jar
-
mysql-connector-java-5.1.37-bin.jar
-
log4j-1.2.17.jar
-
-
編寫
Mybatis
核心配置檔案:mybatis-config.xml
-
連線資料庫四要素
-
<mapper>
標籤中對映檔案路徑不是.
是/
建議複製,不要手敲
-
-
編寫對映檔案:
StudentDao.xml
-
編寫
POJO
類和Dao
層介面,初始化資料庫表及資料 -
SQL
-
實體類
-
介面
-
測試
-
小經驗
-
直接生成
mybatis
的兩類xml
檔案 -
Mybatis
對映配置檔案和介面之間相互跳轉
-
核心配置檔案
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE configuration
3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
5 <configuration>
6 <environments default="development">
7 <environment id="development">
8 <transactionManager type="JDBC"/>
9 <dataSource type="POOLED">
10 <!-- 連線資料庫四要素 -->
11 <property name="driver" value="com.mysql.jdbc.Driver"/>
12 <property name="url" value="jdbc:mysql:///web17_mybatis01"/>
13 <property name="username" value="root"/>
14 <property name="password" value="root"/>
15 </dataSource>
16 </environment>
17 </environments>
18
19
20 <!-- 載入對映配置檔案 -->
21 <mappers>
22 <mapper resource="com/itheima/dao/StudentDao.xml"/>
23 </mappers>
24 </configuration>
對映配置檔案
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!--
3 xml文件第一行是文件宣告,必須在首行
4 接下來是:名稱空間。作用如下:
5 1. 引入dtd檔案
6 2. 對文件中標籤及其屬性進行約束
7 -->
8 <!DOCTYPE mapper
9 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
10 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
11
12 <!-- 把當前這個xml配置檔案當做對應介面的實現類
13 通過namespace屬性指向要被實現的介面,介面代理的方式必須這樣寫
14
15 -->
16 <mapper namespace="com.itheima.dao.StudentDao">
17 <!--
18 標籤名:select 表示查詢
19 id屬性 id唯一標識,要配置被實現的介面中的方法
20 resultType屬性 方法的結果(集合中泛型)的型別,全限定類名,不能省略
21 parameterType屬性,方法發引數的型別,全限定類名,可以省略
22 標籤體中書寫SQL語句
23 整個標籤被稱之為:statement
24
25 -->
26 <select id="findById" resultType="com.itheima.domain.Student">
27 select * from student where id = 1;
28 </select>
29 </mapper>
介面StudentDao.java
1 public interface StudentDao {
2 Student findById();
3 }
測試類MybatisTest.java
View Code2. API
2.1Resources
讀取配置的檔案的工具類
InputStream getResourceAsStream
("配置檔案相對於類路徑的相對路徑");
2.2SqlSessionFactoryBuilder
獲取SqlSessionFactory
工廠物件的功能類。
// 通過構建的方式構建了一個SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//xxxBuilder.build()
2.3SqlSessionFactory
org.apache.ibatis.session.SqlSessionFactory
:獲取SqlSessi
物件的工廠介面。
SqlSession openSession()
獲取SqlSession
物件,並開啟手動提交事務
SqlSession openSession(boolean autoCommit)
獲取SqlSession
物件,true
表示自動提交
2.4SqlSession
org.apache.ibatis.session.SqlSession
:sql會話物件介面。用於執行SQL
、管理事務、介面代理。
void | commit() | 提交事務 |
void | rollback() | 回滾事務 |
T | getMapper(Class cls) | 獲取指定介面的代理實現類物件 |
void | close() | 釋放資源 |
3. 對映配置檔案
編碼完成如下需求:
1 // 需求1:查詢id為1的學生(強制要求) 2 // 需求2:建立一個Student物件並儲存到資料庫(引數和成員變數名保持一致)(成功了嗎?) 3 // 需求3:根據學生姓名和年齡查詢使用者,傳兩個引數(多個引數怎麼辦?) 4 // 需求4:完成需求3,傳一個引數。
對映配置檔案StudentDao.xml
,保證這個檔案的名字和介面名完全一致,且在同一個包下。
核心配置檔案
1 <!-- 載入對映配置檔案 這裡使用的是/ --> 2 <mappers> 3 <mapper resource="com/itheima/dao/StudentDao.xml"/> 4 </mappers>
Dao
層介面StudentDao
1 public interface StudentDao {
2 @Select("select * from student where id = 1")
3 Student findById();
4
5 // 需求1:查詢id為1的學生(強制要求)
6 Student findById2(@Param("id") Integer id);
7
8 // 需求2:建立一個Student物件並儲存到資料庫
9 void save(Student stu);
10
11 // 需求3:根據學生姓名和年齡查詢使用者,傳兩個引數(多個引數怎麼辦?)
12 List<Student> findByNameAndAge(@Param("name") String name, @Param("agex") Integer age);
13
14 // 需求4:完成需求3,傳一個引數。
15 // 4.1 把兩個引數封裝成一個實體物件
16 // 如果把多個引數封裝到一個實體物件中,引數型別有侷限性,不能是兩個一樣的條件做範圍查詢
17 List<Student> findByStudent(Student stu);
18
19 // 4.2 把兩個引數封裝到Map集合中
20 List<Student> findByMap(Map<String,Object> map);
21 }
測試類
1 /**
2 * @Author sonyan
3 * @Date 2020/8/7 11:19
4 * @Description: 測試類
5 */
6 public class MybatisDemo {
7 public static void main(String[] args) throws Exception {
8
9 // 指定核心配置檔案
10 String resource = "mybatis-config.xml";
11 // 把核心配置檔案載入成流 Resources為我們提供的方便讀取配置檔案的工具類
12 InputStream inputStream = Resources.getResourceAsStream(resource);
13
14 // 通過構建的方式構建了一個SqlSessionFactory
15 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
16
17 // SqlSession 就相當於我們之前的 Connection
18 // JDK7新特性 try-with-resource
19 // 需要釋放資源的動作,自動釋放在try()中開啟的一些流、會話......
20 try (SqlSession session = sqlSessionFactory.openSession(true)) {
21
22 // getMapper getDao 獲取一個指定介面的實現類物件
23 // 底層是動態代理
24 // 動態代理可以增強有介面的類、介面(增強介面,就是現實介面)
25 // 就相當於我們自己new StudentDaoImpl();
26 // 這個StudentDaoImpl是Mybatis通過動態代理幫我們自動生成並且賦值給了studentDao
27 StudentDao studentDao = session.getMapper(StudentDao.class);
28
29 /*List<Student> students = studentDao.findAll();
30 System.out.println("students = " + students);*/
31
32
33 // 測試根據id查詢
34 /*Student student = studentDao.findById(1);
35 System.out.println("student = " + student);*/
36
37 // 測試新增學生
38 //studentDao.saveStudent(new Student(null,"鳳姐",20));
39
40 // 根據名稱和年齡查詢使用者,引數是兩個基本型別
41 //List<Student> students = studentDao.findByNameAndAge("美女", 20);
42 //System.out.println("students = " + students);
43
44 // 根據名稱和年齡查詢使用者,引數是一個student物件
45 //List<Student> students = studentDao.findByUser(new Student(null, "鳳姐", 20));
46 //System.out.println("students = " + students);
47
48 // 根據名稱和年齡查詢使用者,引數是一個map集合
49
50 HashMap<String, Object> map = new HashMap<>();
51 map.put("name", "王二蛋");
52 map.put("age", 20);
53
54 System.out.println("studentDao.findByMap(map) = " + studentDao.findByMap(map));
55
56
57 // 手動提交
58 //session.commit();
59
60 // session.close();
61 }
62
63 }
64 }
4. 核心配置檔案
4.1 properties(重要)
引入外部的properties檔案,一般用作引入資料庫連結引數的配置。
核心配置檔案
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <!-- 這是一個mybatis的核心配置檔案,名字任意--> 6 <configuration> 7 <!-- --> 8 <properties resource="jdbc.properties"/> 9 10 <environments default="development"> 11 <environment id="development"> 12 <transactionManager type="JDBC"/> 13 <dataSource type="POOLED"> 14 <property name="driver" value="${jdbc.driver}"/> 15 <property name="url" value="${jdbc.url}"/> 16 <property name="username" value="${jdbc.username}"/> 17 <property name="password" value="${jdbc.password}"/> 18 </dataSource> 19 </environment> 20 </environments> 21 22 <!-- 載入對映配置檔案 --> 23 <mappers> 24 <mapper resource="com/itheima/dao/StudentDao.xml"/> 25 </mappers> 26 </configuration>
jdbc.properties
1 jdbc.driver=com.mysql.jdbc.Driver
2 jdbc.url=jdbc:mysql://192.168.115.130:3306/db1
3 jdbc.username=root
4 jdbc.password=root
4.2Settings
(重要)
1 <!-- 極為重要的設定 --> 2 <settings> 3 <!-- 4 指定 MyBatis 所用日誌的具體實現,未指定時將自動查詢。 5 LOG4J 要求:1. 匯入log4j的jar包 2. 有一個log4j.properties檔案 6 建議顯式的配置上。可配可不配的,建議配上。 7 --> 8 <setting name="logImpl" value="LOG4J"/> 9 10 11 <!-- 12 mapUnderscoreToCamelCase 13 是否開啟駝峰命名自動對映,即從經典資料庫列名 A_COLUMN 對映到經典 Java 屬性名 aColumn。 14 15 Java中多個單詞的屬性名 使用駝峰命名 lastName 16 MySQL不缺分大小寫 底槓命名 last_name 17 18 19 Mybatis可以幫我們自動完成結果集和實體的自動轉換封裝,原因是結果集的欄位名和實體屬性名一致。 20 21 --> 22 <!--<setting name="mapUnderscoreToCamelCase" value="true"/>--> 23 </settings>
4.3TypeAliases
(瞭解)
1 <!-- 起別名 --> 2 <typeAliases> 3 <!-- 4 type 全限定類名 5 alias 別名 6 別名不區分大小寫 7 --> 8 <!--<typeAlias type="com.itheima.domain.Student" alias="student"/>--> 9 10 <!-- 為包下所有的實體類起別名,不區分大小寫 --> 11 <!--<package name="com.itheima.domain"/>--> 12 13 </typeAliases>
起別名後,在對映配置檔案中可以直接使用別名
1 <select id="findByMap" resultType="Student">
2 select * from student where first_username=#{name}
3 and
4 age=#{age}
5 </select>
6
系統為常見的型別起好了別名
4.4Environments
(瞭解)
1 <environments default="dev"> 2 <environment id="dev"> 3 <transactionManager type="JDBC"/> 4 <dataSource type="POOLED"> 5 <!-- 連線資料庫四要素 --> 6 <property name="driver" value="${jdbc.driver}"/> 7 <property name="url" value="${jdbc.url}"/> 8 <property name="username" value="${jdbc.username}"/> 9 <property name="password" value="${jdbc.password}"/> 10 </dataSource> 11 </environment> 12 <environment id="test"> 13 <transactionManager type="JDBC"/> 14 <dataSource type="POOLED"> 15 <!-- 連線資料庫四要素 --> 16 <property name="driver" value="${jdbc.driver}"/> 17 <property name="url" value="${jdbc.url}"/> 18 <property name="username" value="${jdbc.username}"/> 19 <property name="password" value="${jdbc.password}"/> 20 </dataSource> 21 </environment> 22 </environments>
4.5Mappers
(重點)
1 <!-- 載入對映配置檔案 --> 2 <mappers> 3 <!-- 4 使用相對於類路徑的資源引用 可以用 5 每個標籤引入一個Mapper的XML檔案 6 --> 7 <!--<mapper resource="com/itheima/dao/StudentDao.xml"/>--> 8 <!--<mapper resource="com/itheima/dao/CourseDao.xml"/>--> 9 <!--<mapper resource="com/itheima/dao/OrderDao.xml"/>--> 10 11 <!-- 12 使用完全限定資源定位符(URL) 不推薦使用 13 http:// file:// 14 --> 15 <!--<mapper url="file:///var/mappers/AuthorMapper.xml"/>--> 16 17 <!-- 18 載入指定某個的介面,識別介面中的註解 可以用 19 --> 20 <!--<mapper class="com.itheima.dao.StudentDao"/>--> 21 <!--<mapper class="com.itheima.dao.StudentDao"/>--> 22 <!--<mapper class="com.itheima.dao.StudentDao"/>--> 23 24 <!-- 25 把包下所有的對映配置檔案和介面全部載入進來 最推薦使用 26 --> 27 <package name="com.itheima.dao"/> 28 </mappers> 29
5. 經驗分享
5.1 生成Mybatis
配置檔案
本質是新建了一個檔案模板,按照下面的方式新建兩個模板即可(Mybatis-config
、Mybatis-Mapper
)
5.2介面
和對映配置檔案
跳轉
使用一個外掛free-idea-mybatis
。
這個外掛是個zip包,不要解壓,直接安裝即可。
已知bug:
多個模組之間有相同內容會提示/跳轉錯誤,解除安裝其他模組即可。
5.3 ${}和#{}區別(面試題)
##
{} MyBatis 會建立PreparedStatement
引數佔位符,並通過佔位符安全地設定引數(就像使用 ? 一樣)。 這樣做更安全,更迅速,通常也是首選做法
${} 會做字串的拼接,將{}中直接拼直接在 SQL 語句中,可能會有SQL注入的風險,效率更低。但是,如果你需要在SQL語句中直接插入一個不轉義的字串,可以使用這種方式。一般情況下會把表名或者欄位名通過這方方式傳遞到SQL語句中,比方說 ORDER BY後面的列名。
5.4 MybatisUtils工具類抽取
1 public class MybatisUtills {
2
3 // 獲取工廠物件SQLSessionFactory,這個物件一個就可
4 private static SqlSessionFactory ssf = null;
5
6 // 靜態程式碼塊中初始化該物件
7 static {
8 InputStream is = null;
9 try {
10 is = Resources.getResourceAsStream("MyBatisConfig.xml");
11 } catch (IOException e) {
12 e.printStackTrace();
13 }
14 ssf = new SqlSessionFactoryBuilder().build(is);
15 }
16
17 public static SqlSessionFactory getFactory() {
18 return ssf;
19 }
20
21
22 // 獲取SQLSession物件,這個連線物件可以有多個
23 public static SqlSession getSqlSession() {
24 return ssf.openSession(true);
25 }
26
27
28 // 獲取Mapper物件
29 public static <T> T getMapper(Class<T> tClass) {
30 return ssf.openSession(true).getMapper(tClass);
31 }
32
33 }