學習主線
? ? ? ? 必學必會屬于優化的東西。
快速入門需求說明
要求:開發一個MyBatis項目,通過MyBatis的方式可以完成對monster表的crud操作
1.創建mybatis數據庫-monster表
? ? ? ? 主鍵Primary Key默認非空Not null,就省略了
create database `mybatis`
use `mybatis`
create table `monster`(
`id` int AUTO_INCREMENT primary KEY,
`age` int not null,
`birthday` date default null,
`email` varchar(255) not null,
`gender` tinyint not null,
`name` varchar(255) not null,
`salary` double not null
)charset=utf8
2.創建Maven項目,方便項目需要jar包管理
父項目的配置
用父項目來管理子項目
我的IDEA版本:IntelliJ IDEA 2024.3.5
1)創建Maven項目,注意Archetype最好的quickstart類型,圖片中這個目前也能用,畢竟src要刪除
2)刪除src目錄
- 把mybatis的src目刪除
- 將mybatis當做父項目/工程
- 創建新的Module作為子項目
- 這樣子項目可以使用父項目的pom.xml引入
3)pom.xml導入依賴
框架的本質就是一些jar包,包含了一些.class文件
<!--加入依賴--><dependencies><!--mysql依賴--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version><!--<version>5.1.49</version>演示用的舊版本--></dependency><!--mybatis依賴--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><!--scope作用域test,限定只能在test目錄下生效--><scope>test</scope></dependency></dependencies>
子項目的配置
1.選中父項目`mybatis`,右鍵點擊新建,選擇模塊
2.選擇Maven,輸入名稱,注意檢查這兒的父項,是不是我們剛剛點擊右鍵那個父項目,下面選quickstart
然后便可以看到新建的子項目
3.配置pom.xml
解讀:
1.將mybatis作為父頂目管理多個子模塊/子項目
2.父頂目的完整的坐標groupId【組織名】+artifactId【項目名】
3.后面該父頂目會管理多個子模塊/子項目,將來父項目中的引入的依賴可以直接給子項目用, 這樣開發簡單,提高復用性,也便于管理
4.<packaging>pom<packaging>表示父項目以多個子模塊/子項目管理工程
<groupId>com.stein</groupId><artifactId>mybatis</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><!--解讀:modules指定管理的哪些子模塊--><modules><module>mybatis_quickstart</module></modules><!--加入依賴--><dependencies><!--mysql依賴--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version><!--<version>5.1.49</version>演示用的舊版本--></dependency><!--mybatis依賴--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><!--scope作用域test,限定只能在test目錄下生效--><scope>test</scope></dependency></dependencies>
deepseek:關于<packaging>pom</packaging>作用的問題
????????<packaging>pom</packaging>,它表示該項目本身不會生成任何實質性的構件(如 JAR 包、WAR 包等),而是作為一個“項目對象模型(POM)容器”或“聚合器”。
????????packaging=pom其實承擔了雙重角色:既作為聚合模塊的標記(module標簽的容器),又作為繼承關系的源頭(parent標簽的指向對象)。
????????需要強調只有packaging=pom的項目才能同時包含modules和dependencyManagement等特殊配置段,普通jar項目是不允許的——這是Maven的強制約定。
????????它主要包含一個?
<modules>
?列表,列出了它管理的所有子模塊(子項目)的目錄名或相對路徑。
4.配置mybatis-config.xml——核心組件
這個資源文件的存放位置有要求,放到對應子項目src中
1)新建resources文件夾。??我們的maven子項目,沒有resources文件夾,需要自己創建一個。
??????
????????選擇下面已有的resources即可
2)創建src/main/resources/mybatis-config.xml。文件名是可以自定義的
配置文件的內容,不用背,可以參考文檔:入門_MyBatis中文網
官方模版:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//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="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><mappers><mapper resource="org/mybatis/example/BlogMapper.xml"/></mappers>
</configuration>
內容解讀:
????????注意 XML 頭部的聲明,它用來驗證 XML 文檔的正確性。environment 元素體中包含了事務管理和連接池的配置。mappers 元素則包含了一組映射器(mapper),這些映射器的 XML 映射文件包含了 SQL 代碼和映射定義信息。
<configuration><environments default="development"><environment id="development"><!--配置事務管理器--><transactionManager type="JDBC"/><!--配置數據源--><dataSource type="POOLED"><!--默認引用的外部文件--><!--<property name="driver" value="${driver}"/>--><!--<property name="url" value="${url}"/>--><!--<property name="username" value="${username}"/>--><!--<property name="password" value="${password}"/>--><!--配置驅動,這兒簡化,直接寫入--><property name="driver" value="com.mysql.jdbc.Driver"/><!-- 配置連接mysql的url"jdbc:mysql:"是協議;mysql是其中的子協議,用于選擇連接到數據庫的具體驅動程序localhost:3306,是要連接的數據庫的ip地址和端口;127.0.0.1:3306這樣寫也可以mybatis,是要連接的數據庫名稱useSSL=true,使用安全連接,Secure Sockets Layer安全套接字協議;默認是不使用的,需要手動設置& ,實體引用,表示&字符,防止解析錯誤useUnicode=true,表示使用unicode字符集,防止亂碼產生。這是基礎字符集聲明,但不指定具體編碼方式。characterEncoding=utf-8,明確指定Unicode字符的具體編碼格式為UTF-8(而非UTF-16等)不用背,下次直接引用--><property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8"/><!--輸入你自己的用戶名和密碼--><property name="username" value="root"/><property name="password" value="root"/><!--解決jdbc8.0驅動報錯的配置--><property name="driver" value="com.mysql.cj.jdbc.Driver"/></dataSource></environment></environments><!--后面完善--><!--<mappers>--><!-- <mapper resource="org/mybatis/example/BlogMapper.xml"/>--><!--</mappers>--> </configuration>
5.創建src/main/java/com/stein/entity/Monster.java
//1.一個普通的Pojo類
//2.使用原生態的sgl語句查詢結果還是要封裝成對象
//3.要求大家這里的實體類屬性名和表名宇段保特一致。
public class Monster {private Integer id;private Integer age;private Date birthday;private String email;private Byte gender;//測試一下行不行,不行就換回Integerprivate String name;private Double salary;
}構造器,getter and setter...
6.配置Mapper.xml
通過java接口,在xml文件進行實現implement,完成對mysql語句的映射
1)創建接口com/stein/mapper/MonsterMapper.java
2)創建文件com/stein/mapper/MonsterMapper.xml
下面是格式模版,探究已映射的 SQL 語句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper"><select id="selectBlog" resultType="Blog">select * from Blog where id = #{id}</select>
</mapper>
接下來將修改為自己的配置文件
7.將Mapper.xml文件交給mybatis-config.xml文件管理
完善mybatis-config.xml
<!--現在完善--><!--1.這里我門配置需要關聯Mapper.xml--><!--2.這里我們可以通過菜單Path from source root--><!--注意分隔符是/,因為你可以去文件直接復制來自源根的路徑(Path From Source Root)--><mappers><mapper resource="com/stein/mapper/MonsterMapper.xml"/></mappers>
復制文件根路徑的方法:
1)英文版
2)中文版
Java代碼操作DB
1.增加/插入
將下圖中的第2、3步組合,寫一個工具類
1. 創建com/stein/util/MybatisUtils.java
/*** 工具類,可以得到SqlSession*/
public class MybatisUtils {private static SqlSessionFactory sqlSessionfactory;//編寫靜態代碼,初始化sqlSessionFactorystatic{try {String resource = "mybatis-config.xml";//SqlSessionFactoryBuilder ,SqlSessionFactory, SqlSession的獲得順序//獲取到配置文件mybatis-config.xml對應的inputStream//說明:加載文件時,默認到resources目錄=>運行后的工作目錄classesInputStream resourceAsStream = Resources.getResourceAsStream(resource);//無法從 static 上下文引用非 static 字段怎么解決的?也用static?確實sqlSessionfactory = new SqlSessionFactoryBuilder().build(resourceAsStream);} catch (IOException e) {throw new RuntimeException(e);}}//編寫方法,返回SqlSessionpublic static SqlSession getSqlSession(){return sqlSessionfactory.openSession();}
}
-
Builder
?->?Factory
?->?Session
?清晰地劃分了這三個不同生命周期的階段。
總結:
SqlSessionFactoryBuilder
?的存在是為了:
隔離復雜性:?將重量級、一次性的配置解析和初始化邏輯從?
SqlSessionFactory
?中剝離出來。明確職責:?讓?
SqlSessionFactoryBuilder
?專注于構建,讓?SqlSessionFactory
?專注于提供會話。靈活配置:?支持多種配置來源的加載方式。
管理資源:?負責構建過程中臨時資源(如文件流)的正確開閉。
清晰生命周期:?標識出構建過程 (
Builder
) 是一個短暫的、一次性的階段,與長生命周期的工廠 (Factory
) 和短生命周期的會話 (Session
) 區分開。遵循設計原則:?更好地實踐了單一職責原則和建造者模式,提高代碼的可讀性、可維護性和靈活性。
2.創建com/stein/MonsterMapperTest.java
public class MonsterMapperTest {private SqlSession sqlSession;private MonsterMapper monsterMapper;//在每一個@Test方法執行前都執行一次,獲取一次sqlSession@Beforepublic void init(){sqlSession= MybatisUtils.getSqlSession();//獲取到MonsterMapper對象?實際是代理對象 class com.sun.proxy.$Proxy9//底層是使用了動態代理機制MonsterMapper mapper = sqlSession.getMapper(MonsterMapper.class);System.out.println("mapper的運行類型是:"+mapper.getClass());}@Testpublic void test01(){System.out.println("方法f1()已調用");}@Testpublic void test02(){System.out.println("方法f2()已調用");}
}
代碼報錯:
Caused by: java.io.IOException: Could not find resource com/stein/mapper/MonsterMapper.xml
原因是這個xml文件不會自動生成到TargetClasses目錄下,導致找不到該文件,可以通過pom.xml文件進行設置生成。注意設置在父工程的pom.xml文件里,這樣每個子工程都可以統一。
3.完善pom.xml
<build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource><resource><directory>src/main/resources</directory><includes><include>**/*.xml</include><include>**/*.properties</include></includes></resource></resources></build>
刷新列表的三種方法:
1)然后在 Build/構建? 選擇->? ? rebuild project/重新構建模塊 進行重構。
2)或者在maven里面clean
3)實在不行,就來回切換一下maven目錄吧
快速入門-代碼實現
1.增加/插入-insert
1.添加com/stein/MonsterMapperTest.java
public class MonsterMapperTest {private SqlSession sqlSession;private MonsterMapper monsterMapper;//在每一個@Test方法執行前都執行一次,獲取一次sqlSession@Beforepublic void init(){sqlSession= MybatisUtils.getSqlSession();//獲取到MonsterMapper對象?實際是代理對象 class com.sun.proxy.$Proxy9//底層是使用了動態代理機制monsterMapper = sqlSession.getMapper(MonsterMapper.class);System.out.println("monsterMapper的運行類型是:"+monsterMapper.getClass());}@Testpublic void test01(){System.out.println("方法f1()已調用");}@Testpublic void test02(){System.out.println("方法f2()已調用");}@Testpublic void insertMonster(){for (int i = 0; i < 2; i++) {Monster monster = new Monster();monster.setAge(10+i);//設置為當前時間monster.setBirthday(new Date());monster.setEmail("94595892@qq.com");monster.setGender((byte) (i/2));monster.setSalary(5000d+i*1000);monster.setName("大象精No."+i);//monsterMapper.insertMonster(monster);//返回自動生成的主鍵值//System.out.println("monsterId="+monster.getId());}if (sqlSession != null) {//如果是增刪改的操作,需要提交,才能生效sqlSession.commit();System.out.println("添加monster操作成功");//是將連接放回連接池,不是真的關閉sqlSession.close();}}
運行報錯:
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
解決辦法:
? ? ? ? 原因是jdbc8.0的驅動類名,由com.mysql.jdbc.Driver改成了com.mysql.cj.jdbc.Driver
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
2.關于返回主鍵的設置。MonsterMapper.xml
useGeneratedKeys 使用DB生成的主鍵,設置成true
keyProperty 設置成對應的字段名
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--解讀
它的核心作用是將 XML 映射文件與 Mapper 接口進行綁定
-->
<mapper namespace="com.stein.mapper.MonsterMapper"><!--配置insertMonster1.id="insertMonster",就是要實現的接口的方法名2.parameterType="com.stein.entity.Monster",參數類型,表示實現方法的入參/形參的類型,3.名稱唯一的時候(僅java類庫),可以不使用全限定名,但還是建議使用全限定名。自定義的類型要簡寫,需要配置類別名TypeAliases4.要寫入的sql語句,現在sql里面測試一下,再復制進來5.(`age`,`birthday`,`email`,`gender`,`name`,`salary`)表的字段6.(#{age},#{birthday},#{email},#{gender},#{name},#{salary})是傳入monster對象屬性名7.這里#{age} 對應monster.age對象的屬性名,其它一樣--><insert id="insertMonster" parameterType="com.stein.entity.Monster" useGeneratedKeys="true" keyProperty="id"><!--<insert id="insertMonster" parameterType="Monster">要報錯-->INSERT INTO `monster`(`age`,`birthday`,`email`,`gender`,`name`,`salary`)--values(#{age},#{birthday},#{email},#{gender},#{name},#{salary})</insert>
3.添加顯示返回值,MonsterMapperTest.insertMonster()
monsterMapper.insertMonster(monster);//返回自動生成的主鍵值System.out.println("monsterId="+monster.getId());
成功顯示
monsterId=8
monsterId=9
添加monster操作成功
2.刪除-delete
1.接口中添加方法,MonsterMapper.java
//根據id刪除monstervoid delMonster(Integer monsterId);
2.配置/實現方法,MonsterMapper.xml
<!--parameterType表示參數類型,當它是Java類庫時,可以省略,比如java.lang.Integer省略為Integer.下面這兩句居然也行delete from monster where id=#{monsterId}delete from monster where id=#{xyz}--><delete id="delMonster" parameterType="Integer">delete from monster where id=#{id}</delete>
這兒測試了一下,發現Mybatis的容錯率高得嚇人。我把語句寫成了如下兩種,跟實際形參名稱完全不一致,都能通過測試,原因估計是參數唯一。但是不建議。
? ? ? ? delete from monster where id=#{monsterId}
? ? ? ? delete from monster where id=#{xyz}
然后刪除了配置里面的parameterType="Integer",依然可以正常運行。
3.測試代碼。com/stein/MonsterMapperTest.java
@Testpublic void delMonster(){monsterMapper.delMonster(7);if (sqlSession != null) {//如果是增刪改的操作,需要提交,才能生效sqlSession.commit();System.out.println("刪除monsterId=7的操作成功");//是將連接放回連接池,不是真的關閉sqlSession.close();}}
正確刪除了對應的行。
3.修改-update
1.MonsterMapper.java添加接口方法
//修改monstervoid updateMonster(Monster monster);
2.MonsterMapper.xml配置/實現接口方法
<!--還是先在DB測試好語句再復制進來用--><update id="updateMonster" parameterType="com.stein.entity.Monster">update monsterset `age`=#{age},`birthday`=#{birthday},`email`=#{email},`gender`=#{gender},`name`=#{name},`salary`=#{salary}where `id`=#{id}</update>
3.測試代碼。com/stein/MonsterMapperTest.java
@Testpublic void updateMonster(){Monster monster = new Monster();monster.setAge(60);//設置為當前時間monster.setBirthday(new Date());monster.setEmail("94595892@qq.com");monster.setGender((byte)0);monster.setSalary(8000d);monster.setName("小雞仔");monster.setId(9);monsterMapper.updateMonster(monster);if (sqlSession != null) {//如果是增刪改的操作,需要提交,才能生效sqlSession.commit();System.out.println("修改Monster的操作成功");//是將連接放回連接池,不是真的關閉sqlSession.close();}}
成功修改
4.查詢
1.MonsterMapper.java添加接口方法
1)情況1:返回一個Monster結果
//通過id查詢monsterMonster selectMonsterById(Integer monsterId);
2)情況2:返回集合
//查詢返回所有是一個集合List<Monster> selectAllMonster();
插入知識點:
類型別名的配置:類型別名可為 Java 類型設置一個縮寫名字。 它僅用于 XML 配置,意在降低冗余的全限定類名書寫。
src/main/resources/mybatis-config.xml在這個配置文件里面設置
<configuration><!--放在配置的靠前的位置--><typeAliases><typeAlias type="com.stein.entity.Monster" alias="Monster" /></typeAliases>...</configuration>
2.MonsterMapper.xml配置/實現接口方法
沒有配置參數類型,自動配置了
1)返回一個
<select id="selectMonsterById" resultType="Monster">select * from `monster` where id=#{id}</select>
2)如果返回的是集合,那應該設置為集合包含的類型,而不是集合本身的類型。
<!--注意,返回的結果是一個集合,但是返回類型依然要寫集合所包含的類型Monster,而不是集合本身的類型List--><select id="selectAllMonster" resultType="Monster">select * from `monster`</select>
3.測試代碼。com/stein/MonsterMapperTest.java
1)返回一個
@Testpublic void selectMonsterById(){Monster monster = monsterMapper.selectMonsterById(9);System.out.println("monster="+monster);if (sqlSession != null) {//這兒是查詢,不是增刪改的操作,就不需要提交了//sqlSession.commit();System.out.println("查詢Monster的操作成功");//是將連接放回連接池,不是真的關閉sqlSession.close();}}
2)返回集合
@Testpublic void selectAllMonster(){List<Monster> monsters = monsterMapper.selectAllMonster();for (Monster monster : monsters) {System.out.println("monster="+monster);}if (sqlSession != null) {//這兒是查詢,不是增刪改的操作,就不需要提交了//sqlSession.commit();System.out.println("查詢所有Monsters的操作成功");//是將連接放回連接池,不是真的關閉sqlSession.close();}}
測試結果成功
日志輸出-查看SQL
看一個需求:
1.在開發MyBatis程序時,比如執行測試方法,程序員往往需要查看程序底層發給MySQL的SQL語句,到底長什么樣,怎么辦?
2.解決方案:日志輸出
具體操作:
1.查看文檔。配置 -> 設置 -> 設置名
2.配置文件src/main/resources/mybatis-config.xml
參考文檔
配置自己的文件:
<configuration><!--要放在前面,對位置有要求,否則報紅--><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings>...</configuration>
3.測試之前代碼,可以看到具體SQL語句,便于調試
課后練習
1.先創建數據庫表格
2.再配置Mybatis