知識點梳理
詳細講義
一.Mybatis快速入門
1.1 框架介紹
-
框架是一款半成品軟體,我們可以基於這個半成品軟體繼續開發,來完成我們個性化的需求!
-
框架:大工具,我們利用工具,可以快速開發專案 (mybatis也是一個jar包,不過提供的功能更加多)
-
jar包:小工具
-
如圖:
-
生活中的例子,比如蓋房子
-
張三想蓋紅色的房子,他需要先給架構搭起來,然後再給房子圖上紅色
-
李四想蓋藍色的房子,他也需要先給架構搭起來,然後再給房子圖上藍色
-
比如很多人都需要蓋房子,那麼肯定會有很多重複性的工作,比如說基礎架構
-
這時候就有公司出了一個解決方案,準備好了房子的架構(上圖左下角黑色的),誰需要蓋房子,只需要藉助於公司提供的架構,在這個基礎之上進行裝修,塗色即可
-
1.2 ORM介紹 ***
-
ORM(Object Relational Mapping): 物件關係對映
-
object:指的是實體物件,javabean
-
relational:指的是關係型資料庫,比如mysql
-
Mapping: 對映,一 一對應的關係
-
-
指的是持久化資料和實體物件的對映模式,為了解決物件導向與關係型資料庫存在的互不匹配的現象的技術。
-
如圖:
-
簡單說,ORM 就是通過例項物件的語法,完成關係型資料庫的操作的技術,是"物件-關係對映"(Object/Relational Mapping) 的縮寫
-
ORM 把資料庫對映成物件,具體對映關係如下圖:
1.3 原始jdbc操作(查詢資料)
1.4原始jdbc操作(插入資料)
1.5 原始jdbc操作的分析
-
原始 JDBC 的操作問題分析
1. 頻繁建立和銷燬資料庫的連線會造成系統資源浪費從而影響系統效能
-
sql 語句在程式碼中硬編碼,如果要修改 sql 語句,就需要修改 java 程式碼,造成程式碼不易維護
-
查詢操作時,需要手動將結果集中的資料封裝到實體物件中
-
增刪改查操作需要引數時,需要手動將實體物件的資料設定到 sql 語句的佔位符
-
-
原始 JDBC 的操作問題解決方案
1. 使用資料庫連線池初始化連線資源
-
將 sql 語句抽取到配置檔案中
-
使用反射、內省等底層技術,將實體與表進行屬性與欄位的自動對映
-
通過分析原始jdbc操作存在的問題,以及對應的解決方案,那麼在對應的解決方案在完全可以使用MyBatis替代
-
1.6 什麼是Mybatis
-
mybatis 是一個優秀的基於java的持久層框架,它內部封裝了jdbc,使開發者只需要關注sql語句本身,而不需要花費精力去處理載入驅動、建立連線、建立statement等繁雜的過程
-
mybatis通過xml或註解的方式將要執行的各種 statement配置起來,並通過java物件和statement中sql的動態引數進行對映生成最終執行的sql語句
-
最後mybatis框架執行sql並將結果對映為java物件並返回。採用ORM思想解決了實體和資料庫對映的問題,對jdbc 進行了封裝,遮蔽了jdbc api 底層訪問細節,使我們不用與jdbc api 打交道,就可以完成對資料庫的持久化操作
-
MyBatis官網地址:http://www.mybatis.org/mybatis-3/
1.7 Mybatis的快速入門 ***
MyBatis開發步驟:
①新增MyBatis的jar包
②建立Student資料表
③編寫Student實體類
④編寫對映檔案StudentMapper.xml
⑤編寫核心檔案MyBatisConfig.xml
⑥編寫測試類
1.7.1 環境搭建
0) 新建java專案:mybatis01
1) 匯入MyBatis的jar包 (在”今日資料\jar包“ 中,將jar包匯入專案libs下)
-
mysql-connector-java-5.1.37-bin.jar
-
mybatis-3.5.3.jar
-
log4j-1.2.17.jar
2) 建立student資料表
3) 編寫Student實體
package com.itheima.bean;
public class Student {
private Integer id;
private String name;
private Integer age;
//省略get個set方法
}
4) 新建測試類
package com.itheima.dao;
public class StudentTest01 {
/*
查詢全部
*/
5) 編寫src/StudentMapper.xml對映檔案
6) 編寫MyBatis核心檔案: src/MyBatisConfig.xml
1.7.2 編寫測試程式碼
1.8 知識小結
-
框架
框架是一款半成品軟體,我們可以基於框架繼續開發,從而完成一些個性化的需求。
-
ORM
物件關係對映,資料和實體物件的對映。
-
MyBatis
是一個優秀的基於 Java 的持久層框架,它內部封裝了 JDBC。
二.MyBatis的相關api ***
2.1 Resources
-
org.apache.ibatis.io.Resources:載入資源的工具類
-
mybatis的前身就是ibatis
-
-
核心方法
-
如果不使用Resources,那我們可以自己使用類載入器(但是麻煩)
//InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
InputStream is = StudentTest01.class.getClassLoader().getResourceAsStream("MyBatisConfig.xml");
2.2 構建器SqlSessionFactoryBuilder
-
org.apache.ibatis.session.SqlSessionFactoryBuilder:獲取 SqlSessionFactory 工廠物件的功能類
-
核心方法
-
通過載入mybatis的核心檔案的輸入流的形式構建一個SqlSessionFactory物件
InputStream inputStream = Resources.getResourceAsStream("MyBatisConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory fact ory = builder.build(inputStream);
2.3 工廠物件SqlSessionFactory
-
org.apache.ibatis.session.SqlSessionFactory:獲取 SqlSession 構建者物件的工廠介面。
-
核心api
-
程式碼
//3.通過SqlSession工廠物件獲取SqlSession物件
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.執行對映配置檔案中的sql語句,並接收結果
List<Student> list = sqlSession.selectList("StudentMapper.selectAll");-
說明:因為我們的程式碼是執行了一個查詢的語句,所以不用處理事務
-
2.4 SqlSession會話物件 ***
-
org.apache.ibatis.session.SqlSession:構建者物件介面。用於執行 SQL、管理事務、介面代理。
-
核心api
-
SqlSession 例項在 MyBatis 中是非常強大的一個類。在這裡你會看到所有執行語句、提交或回滾事務和獲取對映器例項的方法
-
作用:
-
通過SqlSession物件,主要用途執行sql語句,對資料庫進行操作
-
-
本質:
-
SqlSession 可以理解為相當於一個資料庫連線(Connection 物件),你可以在一個事務裡面執行多條 SQL,然後通過它的 commit、rollback 等方法,提交或者回滾事務
-
所以它應該存活在一個業務請求中,處理完整個請求後,應該關閉這條連線,讓它歸還給SqlSessionFactory,否則資料庫資源就很快被耗費精光,系統就會癱瘓,所以用 try...catch...finally... 語句來保證其正確關閉
-
2.5 小結
-
Resources
-
載入資源的工具類
-
-
SqlSessionFactoryBuilder
-
獲取 SqlSessionFactory 工廠物件的功能類
-
-
SqlSessionFactory
-
獲取 SqlSession 構建者物件的工廠介面
-
指定事務的提交方式
-
-
SqlSession
-
構建者物件介面
-
執行 SQL
-
管理事務
-
介面代理
-
三.MyBatis 對映配置檔案 ***
3.1 對映配置檔案介紹
-
對映配置檔案包含了資料和物件之間的對映關係以及要執行的 SQL 語句
-
這個namespace,名稱空間,相當於是給這個對映節點,起一個名字
-
內部的所有增刪改查的配置,都需要通過這個名稱空間獲取
-
語法:名稱空間.id
-
3.2 查詢功能
-
<select>
:查詢功能標籤 -
屬性
id:唯一標識, 配合名稱空間使用。
parameterType:指定引數對映的物件型別
resultType:指定結果對映的物件型別
-
SQL 獲取引數: #{屬性名}
-
修改StudentMapper.xml,增加如下:
-
因為引數型別是Integer,所以屬性名可以改名字(#{sid})
-
但是這裡的屬性名一般是與資料庫列名一致的
-
為啥叫屬性名,其實應該是引數名,但是這個引數名一般都是與javabean中的屬性名保持一致的,所以叫屬性名
-
-
-
測試類StudentTest01.java,新增程式碼:
/*
根據id查詢
*/
####3.3 新增功能
-
<insert>
:新增功能標籤 -
屬性
id:唯一標識, 配合名稱空間使用
parameterType:指定引數對映的物件型別
resultType:指定結果對映的物件型別
-
SQL 獲取引數: #{屬性名} #{列名}
-
修改StudentMapper.xml,增加如下:
-
注意:因為這裡的引數型別是Student,所以屬性名必須與Student的欄位保持一致
-
-
測試類StudentTest01.java,新增程式碼:
/*
新增功能
*/
3.4 修改功能
-
<update>
:修改功能標籤 -
屬性
id:唯一標識, 配合名稱空間使用
parameterType:指定引數對映的物件型別
resultType:指定結果對映的物件型別
-
SQL 獲取引數: #{屬性名}
-
修改StudentMapper.xml,增加如下:
-
注意:因為這裡的引數型別是Student,所以屬性名必須與Student的欄位保持一致
-
-
測試類StudentTest01.java,新增程式碼:
/*
修改功能
*/
3.5 刪除功能
-
<delete>
:查詢功能標籤。 -
屬性
id:唯一標識, 配合名稱空間使用。
parameterType:指定引數對映的物件型別。
resultType:指定結果對映的物件型別。
-
SQL 獲取引數: #{屬性名}
-
修改StudentMapper.xml,增加如下:
-
測試類StudentTest01.java,新增程式碼:
/*
刪除功能
*/
@Test
public void delete() throws Exception{
//1.載入核心配置檔案
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.獲取SqlSession工廠物件
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通過工廠物件獲取SqlSession物件
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.執行對映配置檔案中的sql語句,並接收結果
int result = sqlSession.delete("StudentMapper.delete",5);
//5.提交事務
sqlSession.commit();
//6.處理結果
System.out.println(result);
//7.釋放資源
sqlSession.close();
is.close();
} -
總結: 大家可以發現crud操作,除了標籤名稱以及sql語句不一樣之外,其他屬性引數基本一致。
3.6 對映配置檔案小結
四.Mybatis核心配置檔案介紹 ***
4.1 核心配置檔案介紹
核心配置檔案包含了 MyBatis 最核心的設定和屬性資訊。如資料庫的連線、事務、連線池資訊等。
如下圖:
4.2 資料庫連線配置檔案引入
-
properties標籤作用:
-
引入外部的資料庫配置檔案
-
-
標籤屬性
-
resource:資料庫連線配置檔案路徑
-
-
獲取資料庫連線引數的語法格式
-
${鍵名}
-
-
優點
-
便於靈活的修改資料庫連線池配置引數.
-
-
建立:src/jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.59.143:3306/db1
username=rooot
password=itheima -
修改MyBatisConfig.xml配置檔案:properties標籤引入外部檔案
<!--引入資料庫連線的配置檔案-->
<properties resource="jdbc.properties"/>
<!-- property獲取資料庫連線的配置資訊 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
4.3 起別名
-
<typeAliases>
:為全類名起別名的父標籤。 -
<typeAlias>
:為全類名起別名的子標籤。 -
屬性
type:指定全類名
alias:指定別名 ([ˈeɪliəs]:別名)
-
<package>
:為指定包下所有類起別名的子標籤。(別名就是類名) -
如下圖:
-
具體如下配置:修改MyBatisConfig.xml,增加程式碼如下:
<!--起別名-->
<typeAliases>
<typeAlias type="com.itheima.bean.Student" alias="student"/>
<!--<package name="com.itheima.bean"/>
如果bean包下有很多Javabean都需要起別名,就可以使用package,指定一個包名
這樣的話,就自動給這個包下所有的類新增別名,別名是類名的小寫名字
-->
</typeAliase>
</typeAliases> -
然後使用的時候就方便了,修改StudentMapper.xml中的com.itheima.bean.Student
<select id="selectAll" resultType="student"> SELECT * FROM student </select> <select id="selectById" resultType="student" parameterType="int"> SELECT * FROM student WHERE id = #{id} </select> <insert id="insert" parameterType="student"> INSERT INTO student VALUES (#{id},#{name},#{age}) </insert> <update id="update" parameterType="student"> UPDATE student SET name = #{name},age = #{age} WHERE id = #{id} </update> <delete id="delete" parameterType="int"> DELETE FROM student WHERE id = #{id} </delete>
4.4 總結
五.Mybatis傳統方式開發
5.1 Dao 層傳統實現方式
-
分層思想:控制層(controller)、業務層(service)、持久層(dao)。
-
呼叫流程
5.1.1 準備工作
-
實現步驟
-
在controller包下: 新建StudentContoller類
-
在service包下: 新建StudentService介面以及StudentServiceImpl實現類
-
在mapper包下:新建StudentMapper介面以及StudentMapperImpl實現類
-
StudentContoller----->StudentService----->StudentMapper
-
-
在mybatis專案中持久層就不再叫dao了,而是叫做mapper(其實都是一樣的,就是換個名字)
-
StudentMapper介面
package com.itheima.mapper; import com.itheima.bean.Student; import java.util.List; /* 持久層介面 */ public interface StudentMapper { //查詢全部 public abstract List<Student> selectAll(); //根據id查詢 public abstract Student selectById(Integer id); //新增資料 public abstract Integer insert(Student stu); //修改資料 public abstract Integer update(Student stu); //刪除資料 public abstract Integer delete(Integer id); }
-
StudentMapperImpl實現類
package com.itheima.mapper.impl; /* 持久層實現類 */ public class StudentMapperImpl implements StudentMapper { /* 查詢全部 */ @Override public List<Student> selectAll() { } /* 根據id查詢 */ @Override public Student selectById(Integer id) { } /* 新增功能 */ @Override public Integer insert(Student stu) { } /* 修改功能 */ @Override public Integer update(Student stu) { } /* 刪除功能 */ @Override public Integer delete(Integer id) { } }
-
StudentService介面
package com.itheima.service; import com.itheima.bean.Student; import java.util.List; /* 業務層介面 */ public interface StudentService { //查詢全部 public abstract List<Student> selectAll(); //根據id查詢 public abstract Student selectById(Integer id); //新增資料 public abstract Integer insert(Student stu); //修改資料 public abstract Integer update(Student stu); //刪除資料 public abstract Integer delete(Integer id); }
-
StudentServiceImpl實現類
package com.itheima.service.impl; import com.itheima.bean.Student; import com.itheima.mapper.StudentMapper; import com.itheima.mapper.impl.StudentMapperImpl; import com.itheima.service.StudentService; import java.util.List; /* 業務層實現類 */ public class StudentServiceImpl implements StudentService { //建立持久層物件 private StudentMapper mapper = new StudentMapperImpl(); @Override public List<Student> selectAll() { return mapper.selectAll(); } @Override public Student selectById(Integer id) { return mapper.selectById(id); } @Override public Integer insert(Student stu) { return mapper.insert(stu); } @Override public Integer update(Student stu) { return mapper.update(stu); } @Override public Integer delete(Integer id) { return mapper.delete(id); } }
-
StudentController測試類:
package com.itheima.controller; import com.itheima.bean.Student; import com.itheima.service.StudentService; import com.itheima.service.impl.StudentServiceImpl; import org.junit.Test; import java.util.List; /* 控制層測試類 */ public class StudentController { //建立業務層物件 private StudentService service = new StudentServiceImpl(); //查詢全部功能測試 @Test public void selectAll() { List<Student> students = service.selectAll(); for (Student stu : students) { System.out.println(stu); } } //根據id查詢功能測試 @Test public void selectById() { Student stu = service.selectById(3); System.out.println(stu); } //新增功能測試 @Test public void insert() { Student stu = new Student(4,"趙六",26); Integer result = service.insert(stu); System.out.println(result); } //修改功能測試 @Test public void update() { Student stu = new Student(4,"趙六",16); Integer result = service.update(stu); System.out.println(result); } //刪除功能測試 @Test public void delete() { Integer result = service.delete(4); System.out.println(result); } }
5.1.2 持久層功能實現
工具類抽取:
package com.itheima.utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; /* 工具類 */ public class MyBatisUtils { // 私有構造方法 private MyBatisUtils(){} // 宣告連線工廠物件 private static SqlSessionFactory sqlSessionFactory; // 靜態程式碼塊,讀取核心配置檔案並工廠物件賦值 static { try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("MyBatisConfig.xml")); } catch (IOException e) { e.printStackTrace(); } } // 提供靜態方法,返回SqlSession物件 public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(true); } }
StudentMapperImpl程式碼:
package com.itheima.mapper.impl; import com.itheima.bean.Student; import com.itheima.mapper.StudentMapper; import com.itheima.utils.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import java.util.List; /* 持久層實現類 */ public class StudentMapperImpl implements StudentMapper { /* 查詢全部 */ @Override public List<Student> selectAll() { // 獲取SqlSession物件 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 List<Student> list = sqlSession.selectList("StudentMapper.selectAll"); // 釋放資源 sqlSession.close(); // 返回結果 return list; } /* 根據id查詢 */ @Override public Student selectById(Integer id) { // 獲取SqlSession物件 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 Student stu = sqlSession.selectOne("StudentMapper.selectById", id); // 釋放資源 sqlSession.close(); // 返回結果 return stu; } /* 新增功能 */ @Override public Integer insert(Student stu) { // 獲取SqlSession物件 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 Integer result = sqlSession.insert("StudentMapper.insert", stu); // 釋放資源 sqlSession.close(); // 返回結果 return result; } /* 修改功能 */ @Override public Integer update(Student stu) { // 獲取SqlSession物件 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 Integer result = sqlSession.update("StudentMapper.update", stu); // 釋放資源 sqlSession.close(); // 返回結果 return result; } /* 刪除功能 */ @Override public Integer delete(Integer id) { // 獲取SqlSession物件 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 Integer result = sqlSession.delete("StudentMapper.delete", id); // 釋放資源 sqlSession.close(); // 返回結果 return result; } /* 查詢指定的資料表 */ @Override public List<Student> selectByTableName(String tableName) { // 獲取SqlSession物件 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 List<Student> list = sqlSession.selectList("StudentMapper.selectByTableName",tableName); // 釋放資源 sqlSession.close(); // 返回結果 return list; } /* 模糊查詢 */ @Override public List<Student> selectLike(String condition) { // 獲取SqlSession物件 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 List<Student> list = sqlSession.selectList("StudentMapper.selectLike",condition); // 釋放資源 sqlSession.close(); // 返回結果 return list; } }
5.2 LOG4J的配置和使用
-
在日常開發過程中,排查問題時難免需要輸出 MyBatis 真正執行的 SQL 語句、引數、結果等資訊,我們就可以藉助 LOG4J 的功能來實現執行資訊的輸出。
-
使用步驟:
-
匯入 jar 包:“01-MyBatis基礎\資料\jar包\log4j-1.2.17.jar”
-
修改核心配置檔案:MyBatisConfig.xml
<!--配置LOG4J:以下name和value是固定寫法--> <settings> <setting name="logImpl" value="log4j"/> </settings>
-
在 src 下編寫 LOG4J 配置檔案 : log4j.properties (配置檔名字也是固定寫法)
# Global logging configuration # 日誌的四個級別,從高到低:ERROR(錯誤資訊) WARN(警告資訊) INFO(普通訊息) DEBUG(除錯資訊,推薦使用) # stdout:輸出到控制檯 log4j.rootLogger=DEBUG, stdout # 輸出格式 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
-
效果
-
錯誤:
Caused by: org.xml.sax.SAXParseException; lineNumber: 41; columnNumber: 17; 元素型別為 "configuration" 的內容必須匹配 "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)"。
這個是因為configuration下的節點順序是有要求的,settings必須是在properties下,放在其他位置會報錯。
-