Mybatis的入門總結
1.三層架構的介紹
軟體中分層
分層的作用
- 降低層與層之間的耦合性。
- 提高軟體的可維護性。
- 提升軟體的可擴充套件性。
小結:
三層架構的好處
- 降低層與層之間的耦合性。
- 提高軟體的可維護性。
- 提升軟體的可擴充套件性。
什麼是框架
之前我們都是根據需求寫出所有的相關程式碼麻煩,累,繁瑣。框架是別人寫好的程式碼,是對常見功能的封裝,是一個半成品。我們在框架的基礎上開發出成品的軟體。
假如你要造一輛馬車,在沒有零件的情況下,你需要自己去伐木,去把木頭做成木板,木棍,然後做成輪子,門,等部件,然後組裝起來,很麻煩。框架就相當於現成的輪子,門等部件。我們只需要拿過來使用即可。
常見框架如:Spring,SpringMVC,Mybatis,JdbcTemplate,Bootstrap等等。
框架解決的問題
提升了開發效率
企業專案中使用框架,程式設計師不再需要重複造輪子,只需要專注實現業務需求,提升了開發效率。
提升了系統穩定性
一個成熟的框架,經過了在眾多企業專案中的驗證使用,穩定性有保障。
持久層框架
MyBatis是一款優秀的持久層框架,MyBatis 避免了幾乎所有的 JDBC程式碼和手動設定引數以及獲取結果集。
關於持久層的框架,還有一個封裝程度更高的框架(hibernate)。該框架相對比較重量級,以及其它各個方面的原因,目前流行程度下降了很多,企業專案中用的越來越少了。
表現層框架
SpringMVC是一種基於Java,實現了Web MVC設計模式,將Web層進行解耦。SpringMVC可以簡化我們日常Web開發。
整合的框架
Spring是一個輕量級控制反轉(IoC)和麵向切面(AOP)的容器框架。讓開發變的更簡單。
什麼是框架:框架是對常見功能的封裝
Mybatiis官方網站
http://www.mybatis.org/mybatis-3/
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-nugTPZu6-1621653693288)(C:\Users\lenovo\Desktop\java筆記\圖片檔案\Mybatis.png)]
小結:
1.Mybatis是一個持久層框架
2.Mybatis的優點:
簡單易學:不需要關注JDBC的資源獲取和釋放,配置SQL對映檔案即可
解除SQL與程式程式碼的耦合:SQL語句和程式碼分離,提高可維護性。
2.Mybatis入門搭建:
開發步驟
- 建立模組 hello-mybatis01
- 建立lib包加入Mybatis-Mysql5.7-log4j jar包
- 編寫使用者類
- 準備核心檔案:sqlMapConfig.xml檔案
- 編寫mapper介面(UserMapper)
- 編寫Mapper介面對映檔案(Usermapper.xml)
- 編寫測試程式碼
-- 建立表
CREATE TABLE USER (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) NOT NULL,
birthday DATE,
sex CHAR(10) ,
address VARCHAR(50)
);
INSERT INTO USER VALUES (NULL, '羅西','1980-10-24','男','45個分站勝利');
INSERT INTO USER VALUES (NULL, '馬奎斯','1992-11-12','女','48個GP勝利');
INSERT INTO USER VALUES (NULL, '斯通納','1983-05-20','男','51次獲勝');
INSERT INTO USER VALUES (NULL, '佩德羅薩','1995-03-22','男','52次獲勝');
INSERT INTO USER VALUES (NULL, '菲爾·雷德','1995-03-22','男','54次獲勝');
INSERT INTO USER VALUES (NULL, '6麥克·杜漢','1995-03-22','女','52次獲勝');
-- 查詢全部資料
SELECT * FROM USER;
1.環境搭建
2.編寫使用者類
/**
使用者實體類物件 */
public class User {
private Integer id; // 主鍵
private String username; // 使用者名稱
private Date birthday; // 生日
private String sex; // 性別
private String address; // 地址
// 省略構造方法/getter/setter/toString
}
3.準備核心檔案:sqlMapConfig.xml檔案
注意sqlMapConfig.xml一定要在src下
<?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="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--1.3配置連線池需要的引數-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.93.222:3306/day19"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--配置介面對映檔案,包掃描-->
<mappers>
<package name="com.xjggb.dao"/>
</mappers>
</configuration>
4.配置日誌檔案 log4j.properties
注意檔案也是放在src下
### 設定Logger輸出級別和輸出目的地 ###
log4j.rootLogger=debug, stdout
### 把日誌資訊輸出到控制檯 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
5.介面的建立UserMapper的建立
package com.xjggb.dao;
import com.xjggb.entity.User;
import java.util.List;
public interface UserMapper {
/*
* 查詢全部
* */
List<User> findListUser();
}
6.UserMapper.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">
<!--namespace屬性:指定DAO介面中類全名-->
<mapper namespace="com.xjggb.dao.UserMapper">
<!--
id:介面中方法的名字
resultType: 返回的資料型別,如果是集合型別,這裡應該指定集合中元素的型別全名
文字:SQL語句查詢全部
-->
<select id="findAllUsers" resultType="com.itheima.entity.User">
<select id="findListUser" resultType="user">
SELECT * FROM USER;
</select>
</select>
</mapper>
7.測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession();
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 物件呼叫方法
List<User> listUser = mapper.findListUser();
// 遍歷
listUser.forEach(s-> System.out.println("s = " + s));
}
}
8.小結
1.Mybatils:實現了SQL與程式碼分離實現瞭解耦性
2.Mybatils:避免了所有的jdbc程式碼和手動設定引數以及獲取結果集
3.用動態代理來建立物件呼叫方法,
3.Mybatils的基本使用CRUD
1.根據使用者id查詢
開發步驟:
1.編寫Usermapper介面
2.編寫Usermapper.xml配置檔案
3.測試
Usermapper介面類
public interface UserMapper {
//根據id查詢使用者
User findUserId(int id);
}
UserMapper.xml檔案
<select id="findUserId" parameterType="int" resultType="user">
SELECT * FROM USER WHERE id=#{uid};
</select>
測試:
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class MybatisTest01 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = builder.build(stream);
SqlSession sqlSession = build.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User findUserBayID = mapper.findUserId(2);
System.out.println("findUserBayID = " + userAndInfo);
}
}
2.新增使用者
新增介面
public interface UserMapper {
int insertUser(User user);
}
Usermapper.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="com.xjggb.dao.UserMapper">
<cache/>
<!-- 使用者新增資料
id介面方法名
parameterType 引數是型別配置檔案做了別名設定別名
-->
<insert id="insertUser" parameterType="user" >
insert into USER values (null,#{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
SqlMapConig.xml檔案
注意新增資料的時候會出現中文亂碼 記得新增 ?useUnicode=true&characterEncoding=UTF-8
<?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>
<settings>
<!--開啟駝峰式命名 資料庫中名字寫 user_name 對映到類中 userName-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--配置別名,包掃描-->
<typeAliases>
<package name="com.xjggb.entity"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--1.3配置連線池需要的引數-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.93.222:3306/day19?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--配置介面對映檔案,包掃描-->
<mappers>
<package name="com.xjggb.dao"/>
</mappers>
</configuration>
測試類
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.List;
public class MybatisTest01 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 建立物件
User user = new User();
// 往物件新增元素
user.setBirthday(Date.valueOf("2019-05-01"));
user.setAddress("我乃行健乖乖霸");
user.setUsername("我是乖乖霸");
user.setSex("男");
// 物件呼叫方法
int i = mapper.insertUser(user);
// 遍歷
System.out.println("i = " + i);
}
}
提交事務
你新增成功資料庫看不到資料是應為事務沒有提交
方式一:手動提交
sqlSession.commit();
方式二:自動提交
SqlSession sqlSession = build.openSession(true);
3.根據id刪除使用者
編寫介面
package com.xjggb.dao;
import com.xjggb.entity.User;
import java.util.List;
public interface UserMapper {
/*
* 根據id刪除使用者
* */
int delectUserByid(int id);
}
編寫UserMapper.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="com.xjggb.dao.UserMapper">
<cache/>
<!--根據使用者id刪除使用者-->
<delete id="delectUserByid" parameterType="int">
DELETE FROM `USER` WHERE id=#{id};
</delete>
</mapper>
4.修改使用者
編寫介面UserMapper.interface介面
public interface UserMapper {
/*
* 修改使用者
* */
int updateUser(User user);
}
編寫UserMapper.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="com.xjggb.dao.UserMapper">
<cache/>
<!--使用者更新資料-->
<update id="updateUser" parameterType="user">
UPDATE `USER` SET username=#{username},birthday=#{birthday},sex=#{sex}, address=#{address} WHERE id=#{id}
</update>
</mapper>
測試類
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;
public class MybatisTest03 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 建立物件
User user = new User();
user.setId(17);
user.setSex("nv");
user.setUsername("吾乃行健乖乖霸");
user.setAddress("我乃行健乖乖霸");
user.setBirthday(Date.valueOf("1980-10-24"));
//根據id修改資料
int i = mapper.updateUser(user);
if (i==1){
System.out.println("新增成功");
}else {
System.out.println("新增失敗");
}
}
}
4.查詢新增的主鍵值
方式一:子元素(常用)
原理在insert語句執行後在執行查詢語句返回新增的主鍵id
屬性 | 說明 |
---|---|
keyColumn | 主鍵表中的欄位,user表的主鍵id列 |
keyProperty | 體類的主鍵屬性名 user中的id |
resultType | 鍵的資料型別 |
order | 執行前 BEFORE 執行後 AFTER |
編寫介面
package com.xjggb.dao;
import com.xjggb.entity.User;
import java.util.List;
public interface UserMapper {
/*
* 新增使用者
* */
int insertUser(User user);
}
編寫UserMapper.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="com.xjggb.dao.UserMapper">
<cache/>
<!-- 使用者新增資料
id介面方法名
parameterType 引數是型別配置檔案做了別名設定別名
-->
<insert id="insertUser" parameterType="user" >
<!-- keyColumn 主鍵表中的欄位,user表的主鍵id列
keyProperty 實體類的主鍵屬性名 user中的id
resultType 主鍵的資料型別
order:
執行前 BEFORE
執行後 AFTER
-->
<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID();
</selectKey>
INSERT INTO USER VALUES (null, #{username}, #{birthday}, #{sex}, #{address})
</insert>
</mapper>
測試程式碼
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.List;
public class MybatisTest01 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 建立物件
User user = new User();
// 往物件新增元素
user.setId(null);
user.setBirthday(Date.valueOf("2019-05-01"));
user.setAddress("我乃行健乖乖霸");
user.setUsername("我是乖乖霸");
user.setSex("男");
// 物件呼叫方法
int i = mapper.insertUser(user);
System.out.println("i = " + user);
}
}
方式二:在insert標籤中增加屬性
屬性 | 說明 |
---|---|
useGeneratedKeys | true,使用mysql生成的主鍵 |
keyColumn | 表中主鍵對應的欄位 |
keyProperty | 實體類中對應的屬性 |
UserMapper介面
package com.xjggb.dao;
import com.xjggb.entity.User;
import java.util.List;
public interface UserMapper {
/*
* 新增使用者
* */
int insertUser(User user);
}
UserMapper.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="com.xjggb.dao.UserMapper">
<cache/>
<!-- 使用者新增資料
id介面方法名
parameterType 引數是型別配置檔案做了別名設定別名
keyColumn 表中主鍵對應欄位
keyProperty 實體類對應的屬性
useGeneratedKeys true 使用Mysql生成的主鍵
-->
<insert id="insertUser" parameterType="user" keyColumn="id" keyProperty="id" useGeneratedKeys="true" >
INSERT INTO USER VALUES (null, #{username}, #{birthday}, #{sex}, #{address})
</insert>
</mapper>
測試類
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.List;
public class MybatisTest01 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 建立物件
User user = new User();
// 往物件新增元素
user.setId(null);
user.setBirthday(Date.valueOf("2019-05-01"));
user.setAddress("我乃行健乖乖霸");
user.setUsername("我是乖乖霸");
user.setSex("男");
// 物件呼叫方法
int i = mapper.insertUser(user);
System.out.println("i = " + user);
}
}
小結:
區別 :useGeneratedKeys 需要條件主鍵必須是自增,而不用
5.sqlMapConfig.xml核心配置檔案
1.properties標籤
目前我們將資料庫相關的資訊都是配置在核心配置檔案中,如果核心配置檔案中的內容很多,那麼修改的時候就不是很方便。我們可以將資料庫的配置資訊專門放到一個單獨的檔案中,使用properties標籤引入即可。
properties的作用:
將外面的屬性檔案(.properties)載入進來。在後面就可以引用屬性檔案中的鍵和值
編寫資料庫連線屬性資原始檔(jdbc.properties)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.93.222:3306/day19?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
編寫SqlMapConfig.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>
<!-- 載入外部檔案-->
<properties resource="jdbc.properties">
</properties>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--1.3配置連線池需要的引數-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--配置介面對映檔案,包掃描-->
<mappers>
<package name="com.xjggb.dao"/>
</mappers>
</configuration>
小結:
-
properties作用是什麼?
引入外部的properties檔案
-
內部配置的property和外面配置的properties如果同名,使用哪個?
使用外部的
url連線時:jdbc:mysql://192.168.93.222:3306/day19?useUnicode=true&characterEncoding=UTF-8
一定要去掉amp;不然就會插入資料亂碼
2.typeAliases標籤設定別名
作用:
我們在介面對映檔案中指定引數或者返回值型別時,需要寫出具體的包名和類名,是比較麻煩的我們可以通過別名更簡單,比如 吉吉國王 簡稱猴子
編寫SqlMapConfig.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>
<!-- 載入外部檔案-->
<properties resource="jdbc.properties">
</properties>
<!--配置別名,包掃描-->
<typeAliases>
<package name="com.xjggb.entity"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--1.3配置連線池需要的引數-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--配置介面對映檔案,包掃描-->
<mappers>
<package name="com.xjggb.dao"/>
</mappers>
</configuration>
小結:
別名的設定不許要寫包名和類名
比如package com.xjggb.entity.User 直接寫成user即可
3.mappers標籤載入介面對映檔案
方式一:
單個載入
<!--對映器-->
<mappers>
<!--
resource: 指定類路徑下對映檔案,注:路徑使用/做為分隔符,而不是點號
class: 指定使用註解的介面名字
-->
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
方式二
包掃描載入mapper對映檔案
1.要求介面對映檔案,與介面放在同一個目錄
2.介面名稱和對映檔名稱一致
<!--配置介面對映檔案,包掃描-->
<mappers>
<package name="com.xjggb.dao"/>
</mappers>
小結:
1.單個載入不方便,包掃描容錯率低更適合團隊開發
2.介面名稱與對映檔案介面一致
3.mappers標籤的作用:配置介面對映檔案位置
4.開啟駝峰式命名
開啟駝峰命名的作用: 將資料庫帶有_的欄位與pojo類的屬性駝峰命名相關聯
例如pojo類有個屬性叫 userName,資料庫對應欄位叫user_name
編寫SqlMapConfig.xml檔案
<settings>
<!--開啟駝峰式命名 資料庫中名字寫 user_name 對映到類中 userName-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="cacheEnabled" value="true"/>
</settings>
6.Mybatis 模糊查詢
方式一
編寫介面
public interface UserMapper {
/*
* 根據名稱模糊查詢
* */
List<User> findUserByUsername(String username);
}
編寫配置檔案UserMapper.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="com.xjggb.dao.UserMapper">
<cache/>
<!--根據使用者名稱模糊查詢-->
<select id="findUserByUsername" parameterType="string" resultType="user">
SELECT * FROM USER WHERE username like #{name};
</select>
</mapper>
測試類
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest04 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest04.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession();
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userByUsername = mapper.findUserByUsername("%乖霸%");
//遍歷陣列
userByUsername.forEach(s-> System.out.println("s = " + s));
}
}
方式二:
UserMapper.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="com.xjggb.dao.UserMapper">
<cache/>
<!--根據使用者名稱模糊查詢-->
<select id="findUserByUsername" parameterType="string" resultType="user">
SELECT * FROM USER WHERE username like'%${value}%';
</mapper>
UsrerMapper介面
public interface UserMapper {
/*
* 根據名稱模糊查詢
* */
List<User> findUserByUsername(String username);
}
測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest04 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest04.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession();
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userByUsername = mapper.findUserByUsername("乖霸");
//遍歷陣列
userByUsername.forEach(s-> System.out.println("s = " + s));
}
}
小結:
#{} 先使用?佔位,後賦值
當引數是基本資料型別或者包裝類或者String
#{隨便寫}
當引數是自定義型別
#{物件的屬性名}
${value}
當引數是基本資料型別
${value}
當引數是自定義型別User
${物件的屬性名}
7.介面對映檔案:
1.resultType輸出型別
1.簡單型別
<!-- 統計使用者表中的女生的使用者數量 -->
<select id="getAmountBySex" resultType="int" parameterType="string">
select count(*) from user where sex=#{sex}
</select>
2.POJO型別
<!--根據使用者id查詢資料-->
<select id="findUserId" parameterType="int" resultType="user">
SELECT * FROM USER WHERE id=#{uid};
</select>
小結
resultType的輸出型別有哪兩種?
- 簡單型別 八大資料型別
- POJO
注意:
parameterType引數型別全部可以省略
resultType返回值型別全部不能省略
2.resultMap輸出對映
Mybatis可以把查詢的結果集自動封裝為物件,但是有要求,資料庫得到列名稱,要以物件的額屬性一致,否則不能正確封裝資料
查詢的列與物件屬性不一致的時候,使用resultMap解決,
配置mapper對映檔案
- 定義resultMap標籤
- id標籤:對映主鍵欄位,如果列名與屬性名相同可以省略
- result標籤:對映普通欄位,指定哪個屬性對應哪個列
- 在查詢的結果中使用resultMap
Usermapper介面
public interface UserMapper {
/*
* 根據id查詢資料
* */
User findUserByid(int id);
}
Usermapper.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="com.xjggb.dao.UserMapper">
<cache/>
<!--對結果集對映-->
<resultMap id="rml" type="user">
<!-- 對查詢結果欄位和類中的成員變數進行對映-->
<!-- id 主鍵的對映-->
<!-- result 普通欄位的對映-->
<!-- column 查詢列名 -->
<!-- property 物件的成員變數名 -->
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</resultMap>
<!-- 根據使用者查詢id-->
<select id="findUserByid" parameterType="int" resultMap="rml">
select * from USER where id=#{id}
</select>
</mapper>
測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest05 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest05.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession();
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userByid = mapper.findUserByid(5);
System.out.println("userByid = " + userByid);
}
}
小結:
resultMap的作用:當實體類的屬性跟資料庫欄位不一致的時候可以用resultMap來對映結果集
8.動態SQL
動態SQL指的是:在程式執行時,根據傳入的引數情況,拼接最終執行的sql語句。
比如淘寶的條件的篩選 價格高低,銷量最高等等
1.動態SQL:if標籤
根據使用者和性別查詢使用者
動態SQL語句:if標籤的使用
if標籤的格式
<if test="條件">
SQL語句
</if>
if標籤的作用:滿足條件就拼接這個SQL
條件全部輸入
編寫介面
public interface UserMapper {
/*
* 動態查詢
* */
List<User> findUserByNameAndSex(User user);
}
編寫配置檔案
<select id="findUserByNameAndSex" parameterType="user" resultType="user">
select * from USER where username=#{username} and sex=#{sex}
</select>
測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest06 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest06.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession();
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 建立物件
User user = new User();
user.setSex("男");
user.setUsername("羅西");
List<User> userByNameAndSex = mapper.findUserByNameAndSex(user);
userByNameAndSex.forEach(s-> System.out.println("s = " + s));
}
}
小結
只有輸入全部條件才能查詢輸入單個條件的時候什麼都查不到,sql沒有拼接成功
動態SQL的使用
- if:判斷使用者名稱稱不為空,且不為空字串,則使用者名稱稱作為查詢條件
- if:判斷使用者性別不為空,且不為空字串,則使用者性別作為查詢條件
UserMapper.xml配置檔案
<select id="findUserByNameAndSex" parameterType="user" resultType="user">
select * from USER where
<if test="username!=null and username!=''">
username like '%${username}%'
</if>
<!--&&與操作要轉義 & &-->
<if test="sex!=null && sex!=''"></if>
and sex=#{sex}
</select>
小結:
if標籤不能去掉and或者or
2.where標籤的作用
where標籤作用
- 相當於where關鍵字,自動補全where這個關鍵字
- 去掉多餘的and和or關鍵字
- 標籤寫在裡面
UserMapper.xml檔案
<select id="findUserByNameAndSex" parameterType="user" resultType="user">
select * from USER
<where>
<if test="username!=null and username!=''">
username like #{username}
</if>
<!--&&與操作要轉義 & &-->
<if test="sex!=null && sex!=''">
AND sex=#{sex}
</if>
</where>
</select>
小結
where標籤的作用相當於whrer關鍵字:
1.需要的時候就加上
2.可以去掉多餘的AND 和OR
3.建議if標籤和whrer標籤一起使用
4.當全部條件都不輸入就會全表掃描
3.動態SQL:set標籤
set標籤的作用
- 用在update語句中,相當於set關鍵字
- 去掉SQL程式碼片段中後面多餘的逗號
有經驗得都知道資料更新部分的時候不更新的資料就會變成null
編寫UserMapper介面
/*
* 修改使用者
* */
int updateUser(User user);
編寫Usermapper.xml檔案
<!--使用者更新資料-->
<update id="updateUser" parameterType="user">
UPDATE `USER` SET username=#{username},birthday=#{birthday},sex=#{sex}, address=#{address} WHERE id=#{id}
</update>
測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;
public class MybatisTest03 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest01.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 建立物件
User user = new User();
user.setId(17);
user.setSex("nv");
user.setUsername("吾乃行健乖乖霸");
user.setAddress("我乃行健乖乖霸");
user.setBirthday(Date.valueOf("1980-10-24"));
//根據id修改資料
int i = mapper.updateUser(user);
if (i==1){
System.out.println("修改成功");
}else {
System.out.println("修改失敗");
}
}
}
小結:
按部分更新的時候更新成功後,其他的欄位就會為null值
這樣存在問題,沒有值的欄位也會被更新為null,最好是有資料的欄位更新,沒有資料的欄位不更新。
使用set標籤進行判斷,如果有值就更新,沒有值就不更新。
<!--使用者更新資料-->
<update id="updateUser" parameterType="user">
UPDATE `USER`
<set>
<if test="username!=null and username!=''">
username=#{username},
</if>
<if test="birthday!=null">
birthday=#{birthday},
</if>
<if test="sex!=null and sex!=''">
sex=#{sex},
</if>
<if test="address!=null and address!=''">
address=#{address}
</if>
</set>
where id=#{id}
</update>
小結:
set標籤的作用:
1.表示Set關鍵字去掉多餘的逗號
2.有值就更新,沒有值就不更新
9.foreach標籤的使用
方式一
foreach標籤:遍歷陣列得到基本型別的資料
實現批量刪除使用者
介面
/*
* 批量刪除使用者
* */
int deleteUserList(int[] id);
對映檔案
<!--批量的刪除使用者-->
<delete id="deleteUserList" parameterType="list">
delete from USER where
<!--
collection: 取值為array表示遍歷的是陣列
open: 遍歷前新增的符號
close: 遍歷最後新增的符號
separator:分隔符
item: 表示每個元素的變數名
-->
<foreach collection="array" open="id in (" close=");" separator="," item="temp">
#{temp}
</foreach>
</delete>
測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest07 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest07.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int[] o={28,29,30};
int i = mapper.deleteUserList(o);
System.out.println("i = " + i);
}
}
小結
foreach標籤:遍歷陣列或集合
- collection:指定遍歷的是陣列還是集合 array表示陣列
- open:迴圈前的內容
- close:迴圈後的內容
- item:每次迴圈遍歷到的資料
- separator:每次迴圈後拼接的內容
方式二
儲存多個使用者到資料庫中
介面
/*
* 同時新增多個使用者
* */
int addUsers(List<User> listUser);
對映檔案
<!--同時新增多個使用者-->
<insert id="addUsers" parameterType="list">
<!--
collection 要遍歷的集合使用list
item 設定變數名,代表每個遍歷的元素
separator 每次遍歷完後新增一個分隔符
#{變數名.屬性} 來引用每個屬性中的值
-->
INSERT INTO USER VALUES
<foreach collection="list" item="user" separator=",">
(null, #{user.username}, #{user.birthday}, #{user.sex}, #{user.address})
</foreach>
</insert>
測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
public class MybatisTest08 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest08.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = new ArrayList<>();
users.add(new User(null,"牛魔王", Date.valueOf("1980-01-30"),"男","火焰山"));
users.add(new User(null,"紅孩兒", Date.valueOf("2009-05-08"),"男","火雲洞"));
users.add(new User(null,"玉面狐狸", Date.valueOf("2005-11-01"),"女","狐狸洞"));
mapper.addUsers(users);
}
}
小結
foreach:迴圈添拼接內容
- collection:指定遍歷的是集合或陣列, list表示遍歷集合
- item:迴圈遍歷到的一個元素
- separator:分隔符,每次迴圈後拼接的內容
注意:取資料需要 #{user.username}
10.sql和include標籤
我們發現在介面對映檔案中會出現很多相同的SQL語句,每個地方都寫一遍有些麻煩。我們可以把相同的SQL語句抽取出來,在需要的地方引入即可。
sql和include標籤的作用
- sql標籤:定義一段SQL語句,起個名字可以重用。
- include標籤:引入上面定義的SQL程式碼段。
<!--抽取重複程式碼-->
<sql id="listUser">
INSERT INTO USER VALUES
</sql>
<!--同時新增多個使用者-->
<insert id="addUsers" parameterType="list">
<!-- 引用抽取的程式碼-->
<include refid="listUser"/>
<!--
collection 要遍歷的集合使用list
item 設定變數名,代表每個遍歷的元素
separator 每次遍歷完後新增一個分隔符
#{變數名.屬性} 來引用每個屬性中的值
-->
<foreach collection="list" item="user" separator=",">
(null, #{user.username}, #{user.birthday}, #{user.sex}, #{user.address})
</foreach>
</insert>
小結
- sql標籤的作用:抽取一段sql語句
- include標籤的作用:引用抽取的SQL語句
11.多表關聯
回顧表的關係
-
一對一關聯
任何身份證的關係
中國的夫妻關係
-
一對多關聯關係
一個使用者有多個訂單
一個老師可以有多個學生
-
多對多關聯
老師與學生:一個老師教多個學生,一個學生也可以跟多個老師學習
使用者與角色:一個使用者多個角色,一個角色多個使用者
實際開發中專案中,多對多的關係通過中間表,看成兩個一對多關聯關係
一對一關聯
使用者的擴充套件資訊
CREATE DATABASE day19;
USE day19;
-- 建立使用者基本表
CREATE TABLE USER (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) NOT NULL,
birthday DATE,
sex CHAR(1) DEFAULT '男',
address VARCHAR(50)
);
INSERT INTO USER VALUES (NULL, '孫悟空','1980-10-24','男','花果山水簾洞');
INSERT INTO USER VALUES (NULL, '白骨精','1992-11-12','女','白虎嶺白骨洞');
INSERT INTO USER VALUES (NULL, '豬八戒','1983-05-20','男','福臨山雲棧洞');
INSERT INTO USER VALUES (NULL, '蜘蛛精','1995-03-22','女','盤絲洞');
-- 使用者擴充套件資訊表,一個使用者對應一條使用者擴充套件資訊
CREATE TABLE user_info (
id INT PRIMARY KEY, -- 既是主鍵又是外來鍵
height DOUBLE, -- 身高釐米
weight DOUBLE, -- 體重公斤
married TINYINT, -- 是否結婚,1為結婚,0為未婚
FOREIGN KEY (id) REFERENCES USER(id)
);
-- 插入使用者擴充套件資訊表
INSERT INTO user_info VALUES(1,185,90,1),(2,170,60,0);
開發流程
- 編寫實體類
- 編寫介面
- 編寫對映檔案
- 測試
實體類
public class User implements Serializable {
private Integer id; // 主鍵
private String username; // 使用者名稱
private Date birthday; // 生日
private String sex; // 性別
private String address; // 地址
// 一個使用者包含一個
private UserInfo userInfo;
//省略getset方法
}
public class UserInfo {
private Integer id; // 主鍵
private Double height; // 身高
private Double weight; // 體重
private Boolean married; // 是否結婚
//省略getset方法
}
編寫介面
package com.xjggb.dao;
import com.xjggb.entity.User;
public interface UserinfoMapper {
/*
* 查詢使用者的擴充套件資訊
* */
User findUserAndInfo(int uid);
}
編寫配置檔案
association標籤的作用:用來指定類的一對一關聯關係
association標籤屬性 :
property :指定另一方的物件屬性名字 如userInfo
javaType:指定另一方的類名
<resultMap id="userAndInfo" type="user" >
<!-- id主鍵的對映
result普通欄位的對映
column 資料庫列名
property 物件屬性名
-->
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<!-- 一對一關聯 user包含一個Userinfo類-->
<association property="userInfo" javaType="com.xjggb.entity.UserInfo">
<id column="id" property="id"/>
<result column="height" property="height"/>
<result column="weight" property="weight"/>
<result column="married" property="married"/>
</association>
</resultMap>
<select id="findUserAndInfo" parameterType="int" resultMap="userAndInfo">
SELECT * FROM `USER` u INNER JOIN user_info f ON u.id=f.id WHERE u.id=#{id};
</select>
測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.dao.UserinfoMapper;
import com.xjggb.entity.User;
import com.xjggb.entity.UserInfo;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
public class MybatisTest09 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest09.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserinfoMapper mapper = sqlSession.getMapper(UserinfoMapper.class);
User userAndInfo = mapper.findUserAndInfo(1);
System.out.println("userAndInfo = " + userAndInfo);
}
}
注意關聯的時候使用resultMap標籤封裝結果時,即使欄位名和類名的屬性相同用也需要指定這樣太麻煩了
可以用autoMapping=“true”
<resultMap id="userAndInfo" type="user" autoMapping="true">
<id column="id" property="id"/>
<!--
association:一對一關聯關係,對另一個物件的對映
property: 一對一類中的成員變數名
javaType: 一對一類中的型別
-->
<association property="userInfo" javaType="com.xjggb.entity.UserInfo" autoMapping="true">
<id column="id" property="id"/>
</association>
</resultMap>
<select id="findUserAndInfo" parameterType="int" resultMap="userAndInfo">
SELECT * FROM `USER` u INNER JOIN user_info f ON u.id=f.id WHERE u.id=#{id};
</select>
小結
1.一對一關聯實體類的關係
public class User implements Serializable {
private Integer id; // 主鍵
private String username; // 使用者名稱
private Date birthday; // 生日
private String sex; // 性別
private String address; // 地址
// 一個使用者包含一個
private UserInfo userInfo;
//省略getset方法
}
2.一對一的關聯標籤
3.當資料欄位和屬性名相同時 resultMap欄位對映的時候可以用autoMapping="true"屬性不要漏掉id有可能會報錯
一對多關聯
查詢使用者的多個訂單
collection的屬性 | 說明 |
---|---|
property | 多方屬性的名稱比如 orderForms |
javaType | 屬性的型別 |
ofType | 每個元素的型別 |
開發步驟
- 建立資料表
- 編寫實體類
- Mapper介面新增方法
- 介面配置檔案SQL
- 測試
建立資料表
-- 建立訂單表
CREATE TABLE order_form (
oid INT PRIMARY KEY AUTO_INCREMENT , -- 主鍵
user_id INT NOT NULL, -- 使用者id,外來鍵
number VARCHAR(20), -- 訂單編號
create_time DATETIME, -- 下單時間
note VARCHAR(100), -- 備註
FOREIGN KEY(user_id) REFERENCES USER(id) -- 外來鍵約束,關聯主表的主鍵
);
-- 新增訂單資料
INSERT INTO order_form VALUES(NULL, 1,'10001001', NOW(), '小米9袋'),(NULL, 1,'10001002', NOW(), '9袋小米'),(NULL, 1,'10001003', NOW(), '小米9手機');
INSERT INTO order_form VALUES(NULL, 2,'10001004', NOW(), '逃生錘'),(NULL, 2,'10001005', NOW(), '安全帶');
實體類
public class User implements Serializable {
private Integer id; // 主鍵
private String username; // 使用者名稱
private Date birthday; // 生日
private String sex; // 性別
private String address; // 地址
// 一個使用者包含一個
private UserInfo userInfo;
// 一個使用者多個訂單
private List< OrderForm> orderForms;
// 省略getset方法
public class OrderForm {
private Integer oid; //主鍵
private Integer userId; //外來鍵
private String number; //訂單號
private Timestamp createTime; //下單時間
private String note; //備註資訊
// 省略getset方法
編寫介面
/*
* 查詢使用者的訂單
* */
User findUserListOrdrForm(int oid);
編寫配置檔案
<resultMap id="mappingUserAndOrderForm" type="user">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<collection property="orderForms" javaType="List" ofType="OrderForm">
<id column="oid" property="oid"/>
<result column="userId" property="userId"/>
<result column="number" property="number"/>
<result column="create_time" property="createTime"/>
<result column="note" property="note"/>
</collection>
</resultMap>
<select id="findUserListOrdrForm" parameterType="int" resultMap="mappingUserAndOrderForm">
SELECT * FROM `USER` u JOIN order_form f ON u.id=f.`user_id` WHERE u.id=#{oid}
</select>
測試
package com.xjggb.test;
import com.xjggb.dao.UserinfoMapper;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class MybatisTest10 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest10.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserinfoMapper mapper = sqlSession.getMapper(UserinfoMapper.class);
User userListOrdrForm = mapper.findUserListOrdrForm(1);
System.out.println("userListOrdrForm = " + userListOrdrForm);
}
}
小結:
1.實體類的配置關係
public class User implements Serializable {
private Integer id; // 主鍵
private String username; // 使用者名稱
private Date birthday; // 生日
private String sex; // 性別
private String address; // 地址
// 一個使用者包含一個
private UserInfo userInfo;
// 一個使用者多個訂單
private List< OrderForm> orderForms;
// 省略getset方法
2.使用collection標籤配置一對多
多對多關聯
多對多關聯關係,可以通過中間表看成兩個雙向的一對多關聯關係。
使用者與角色多對多關係模型
一個使用者對應多種角色
一種角色可以有多個使用者
多對多的關係
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-hrtzfKZJ-1621653693299)(H:\學習筆記\java筆記\圖片檔案\對對多.jpg)]
實體類
public class Role {
private Integer roleId;
private String roleName;
private String roleDetail;
//一個角色多個使用者
private List<User> users;
public class User implements Serializable {
private Integer id; // 主鍵
private String username; // 使用者名稱
private Date birthday; // 生日
private String sex; // 性別
private String address; // 地址
// 一個使用者包含一個
private UserInfo userInfo;
// 一個使用者多個訂單
private List< OrderForm> orderForms;
//一個使用者多個角色
private List<Role> roles;
編寫介面
/**
通過 uid 查詢使用者和他的所有角色
*/
User findRolesByUserId(int uid);
/**
通過 role_id 查詢角色和他的所有使用者
*/
Role findUsersByRoleId(int roleId);
編寫xml檔案
<!--多對多查詢-->
<resultMap id="useRoleMapMore" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<collection property="roles" javaType="list" ofType="Role">
<id property="roleId" column="role_id"/>
<result property="roleName" column="role_name"/>
<result property="roleDetail" column="role_detail"/>
</collection>
</resultMap>
<!--多對多,通過使用者id查詢到一個使用者裡面的多個角色-->
<select id="findRolesByUserId" parameterType="int" resultMap="useRoleMapMore">
SELECT u.*, r.* FROM USER u INNER JOIN user_role ur ON u.id = ur.user_id INNER JOIN role r ON ur.role_id = r.role_id WHERE u.id = #{id};
</select>
<resultMap id="us" type="role">
<id property="roleId" column="role_id"/>
<result property="roleName" column="role_name"/>
<result property="roleDetail" column="role_detail"/>
<collection property="users" javaType="list" ofType="User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
</collection>
</resultMap>
<!--多對多,通過使用者id查詢到一個使用者裡面的多個角色-->
<select id="findUsersByRoleId" parameterType="int" resultMap="us">
SELECT u.*, r.* FROM USER u INNER JOIN user_role ur ON u.id = ur.user_id INNER JOIN role r ON ur.role_id = r.role_id WHERE r.role_id = #{id};
</select>
測試
package com.xjggb.test;
import com.xjggb.dao.UserinfoMapper;
import com.xjggb.entity.Role;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest11 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest11.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserinfoMapper mapper = sqlSession.getMapper(UserinfoMapper.class);
User rolesByUserId = mapper.findRolesByUserId(1);
List<Role> roles = rolesByUserId.getRoles();
roles.forEach(s-> System.out.println("s = " + s));
System.out.println("rolesByUserId = " + rolesByUserId.getRoles());
}
}
package com.xjggb.test;
import com.xjggb.dao.UserinfoMapper;
import com.xjggb.entity.Role;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest12 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest12.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession(true);
// 通過動態代理建立物件
UserinfoMapper mapper = sqlSession.getMapper(UserinfoMapper.class);
Role usersByRoleId = mapper.findUsersByRoleId(1);
List<User> users = usersByRoleId.getUsers();
users.forEach(s-> System.out.println("s = " + s));
}
}
小結
1.多對多在實體類中就是配置兩個一對多
private Integer id; // 主鍵
private String username; // 使用者名稱
private Date birthday; // 生日
private String sex; // 性別
private String address; // 地址
//一個使用者多個角色
private List<Role> roles;
private Integer roleId;
private String roleName;
private String roleDetail;
//一個角色多個使用者
private List<User> users;
2.多對多需要兩條sql按照使用者id 或者角色id進行查詢
12.Mybatis懶載入
一對一延遲載入
延遲載入介紹
延遲載入概念:也叫懶載入。指的是按需載入,在實際用到資料的時候才載入。
如:查詢使用者資訊,不需要他的擴充套件資訊。但後面有可能又需要用到,這時候可以通過延遲載入來實現。當需要擴充套件資訊的時候,再發送一條SQL語句來查詢擴充套件資訊。好處是,只有在需要的時候才查詢相應資料。提升查詢的效率。相當於每次只查詢1張表,而不是一次使用表連線查詢所有的資訊。
一對一關聯查詢使用標籤:association
一對多關聯查詢使用標籤:collection
要求
-
通過id查詢1號使用者User的基本資訊
-
使用延遲載入的方式,關聯查詢出對應的使用者擴充套件資訊UserInfo
SQL語句分析
SELECT * FROM USER WHERE id=1;
SELECT * FROM user_info WHERE id=1;
介面檔案
/**
持久層介面:UserMapper
*/
public interface UserMapper {
/**
通過id查詢1個使用者
*/
User findUserById(int id);
/**
通過id查詢1個使用者擴充套件資訊
*/
UserInfo findUserInfoById(int id);
}
mapper.xml檔案
<resultMap id="useMapOne" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!--一對一關聯關係,User類中包含一個UserInfo類,名稱為userInfo-->
<association property="userInfo" column="id" javaType="UserInfo" select="findUserInfoById" fetchType="lazy"/>
</resultMap>
<select id="findUserById" parameterType="int" resultMap="useMapOne">
SELECT * FROM USER WHERE id=#{uid};
</select>
<select id="findUserInfoById" parameterType="int" resultType="UserInfo">
SELECT * FROM user_info WHERE id=#{uid};
</select>
x小結:
一對一延遲載入需要將一個SQL拆成兩個SQL
- 通過id查詢使用者物件
- 輸出使用者名稱和性別的屬性
注意:
不要使用斷點除錯,無法看到懶載入
不要直接輸出user物件,因為會觸發toString()方法,導致立即載入userInfo物件
@Test
public void testFindUserAndInfo() {
User user = userMapper.findUserById(1);
System.out.println(user.getUsername());
System.out.println("----------------");
//然後在檢視延遲載入的資料
System.out.println(user.getUserInfo());
}
<resultMap id="userAndInfo" type="user" autoMapping="true">
<!--association 一對一關係配置
property: 一方的成員變數名
javaType: 一方的型別
select: 要執行的SQL語句,通過這個SQL語句會得到UserInfo
fetchType: lazy表示懶載入, eager表示立即載入
column: 第一個sql語句結果的某個欄位,作為第二個sql語句的引數
-->
<association property="userInfo" javaType="UserInfo" select="findUserInfoById" column="id" fetchType="lazy"></association>
</resultMap>
<select id="findUserById" resultMap="userAndInfo">
SELECT * FROM USER WHERE id=#{uid};
</select>
<!--查詢擴充套件資訊-->
<select id="findUserInfoById" resultType="UserInfo">
SELECT * FROM user_info WHERE id=#{infoId};
</select>
一對多延遲載入
association標籤
association標籤的屬性 | 說明 |
---|---|
property | 一方的成員變數名 |
column | 第一個sql語句結果的某個欄位,作為第二個sql語句的引數 |
select | 懶載入的sql語句 |
fetchType | lazy: 懶載入 eager: 立即載入 |
表連線查詢一次性查出所有資料。
SELECT * FROM USER u INNER JOIN order_form o ON u.id = o.user_id WHERE u.id=1;
分成兩個SQL語句
-- 查詢1號使用者資料
SELECT * FROM USER WHERE id=1;
-- 查詢1號使用者的訂單表,使用延遲載入方式實現
SELECT * FROM order_form WHERE user_id=1;
新增介面
/**
通過id查詢1個使用者
*/
User findUserById(int id);
/**
通過userId查詢這個使用者所有的訂單資訊
*/
List<OrderForm> findOrdersByUserId(int userId);
<resultMap id="useMapOne" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!--多對多,通過使用者id查詢到一個使用者裡面的多個角色-->
<collection property="orders" column="id" javaType="List" ofType="OrderForm" select="findOrdersByUserId" fetchType="lazy"/>
</resultMap>
<select id="findUserById" parameterType="int" resultMap="useMapOne">
SELECT * FROM USER WHERE id=#{uid};
</select>
<select id="findOrdersByUserId" parameterType="int" resultType="OrderForm">
SELECT * FROM order_form WHERE user_id=#{uid};
</select>
配置sqlMapConfig.xml,開啟MyBatis延遲載入
如果有多個延遲載入需要配置。可以在sqlMapConfig.xml核心配置檔案中統一配置一次即可
開啟延遲載入的settings中的lazyLoadingEnabled
<!--全域性設定-->
<settings>
<!--開啟延遲載入-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
小結
-
一對多延遲載入需要將一個SQL拆成兩個SQL
-- 先載入使用者的基本資訊 SELECT * FROM USER WHERE id=1; -- 再懶載入多個訂單 SELECT * FROM order_form WHERE user_id=1;
-
配置延遲載入屬性
<resultMap id="userAndInfo" type="user" autoMapping="true">
<!--collection 一對多關係配置
-->
<collection property="orderForms" javaType="list" ofType="orderform" select="findOrdersByOrderId" column="id" ></collection>
</resultMap>
collection標籤的屬性
collection標籤的屬性 | 說明 |
---|---|
property | 多方的屬性名 |
column | 這個查詢結果的指定欄位值作為下一個查詢的SQL的引數 |
select | 下個查詢懶載入 |
13.Mybatis快取
一級快取
現在我們每次執行相同的SQL語句都是去資料庫中查詢,存在效率問題。Mybatis提供了快取方案可以提高重複查詢資料的效率。
Mybatis快取介紹
Mybatis 框架提供了快取策略,通過快取策略可以減少查詢資料庫的次數,提升系統性能。在 Mybatis 框架中
快取分為一級快取和二級快取。
一級快取是 sqlSession 範圍的快取,只能在同一個 sqlSession 內部有效。它本身已經存在,一級快取不需要手動處理,可以直接使用。
小結
-
快取有什麼好處?
相同的sql語句避免頻繁的訪問資料庫,使用快取效率高
-
一級快取的範圍?
每個SqlSession內部都有一個一級快取
-
一級快取何時失效?
增刪改提交事務,手動清除
二級快取
二級快取概述
二級快取是 mapper 對映級別快取,作用範圍跨越SqlSession,即可以在多個 SqlSession 之間共享二級快取
資料。
二級快取關鍵點
- 實體類需要實現Serializable介面
- 至少要準備2個SqlSession,再進行測試。
配置二級快取
在sqlMapConfig.xml配置
<settings>
<!--開啟駝峰式命名 資料庫中名字寫 user_name 對映到類中 userName-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 開啟二級快取-->
<setting name="cacheEnabled" value="true"/>
</settings>
在mapper.xml檔案
<mapper namespace="com.itheima.dao.UserMapper">
<!--開啟二級快取,當前Mapper裡的所有查詢的資料都會放入二級快取中-->
<cache/>
<select id="findUserById" parameterType="int" resultMap="useMapOne">
SELECT * FROM USER WHERE id=#{uid};
</select>
</mapper>
14.註解開發
1.查詢使用者的全部資料
編寫介面
/*
* 使用者的全部資料
* */
@Select("select * from USER")
List<User> queryListUser();
SqlMapconfig.xml檔案
<!--配置介面對映檔案,包掃描-->
<mappers>
<package name="com.xjggb.dao"/>
</mappers>
測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.dao.UserMapper01;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest13 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest13.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession();
// 通過動態代理建立物件
UserMapper01 mapper = sqlSession.getMapper(UserMapper01.class);
List<User> users = mapper.queryListUser();
users.forEach(s-> System.out.println("s = " + s));
}
}
2.使用@Results和@Result屬性
使用註解方式對結果集對映
註解說明會
註解 | 屬性 | 說明 |
---|---|---|
@Results | 相當於resultMap表示對結果集的對映 | |
@Result | column properly id=true | 查詢的欄位名 類中的成員變數名 表示主鍵 |
編寫介面
/*
* 使用者的全部資料
* */
@Select("select * from USER")
@Results({ @Result(id = true , column = "id",property = "id"),
@Result(column ="username" ,property = "username"),
@Result(column ="birthday" ,property = "birthday"),
@Result(column ="sex" ,property = "sex"),
@Result(column ="address" ,property = "address")
})
List<User> queryListUser();
測試
package com.xjggb.test;
import com.xjggb.dao.UserMapper;
import com.xjggb.dao.UserMapper01;
import com.xjggb.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class MybatisTest13 {
public static void main(String[] args) {
//載入配置檔案
InputStream stream = MybatisTest13.class.getResourceAsStream("/sqlMapConfig.xml");
// 會話工廠建造類
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 會話工廠
SqlSessionFactory build = builder.build(stream);
// 會話
SqlSession sqlSession = build.openSession();
// 通過動態代理建立物件
UserMapper01 mapper = sqlSession.getMapper(UserMapper01.class);
List<User> users = mapper.queryListUser();
users.forEach(s-> System.out.println("s = " + s));
}
}
小結
@Select註解作用?
存放查詢的SQL語句
@Results註解作用?
相當於resultMap標籤,對查詢結果進行對映
@Result註解作用?
將一個欄位對映到類中的成員變數
3.根據使用者id修改使用者(@Update)
UserMapper介面:新增修改資料方法,在方法上使用註解@Update(“SQL語句”)
介面
/*
根據使用者Id修改使用者
*/
@Update("UPDATE user SET username=#{username}, birthday=#{birthday}, sex=#{sex}, address=#{address} WHERE id=#{id}")
void updateUser(User user);
4.根據使用者id刪除使用者(@Delete)
/*
根據使用者id刪除使用者
*/
@Delete("DELETE FROM user WHERE id=#{id}")
void deleteUser(Integer id);
5.新增使用者(@Insert)
/*
新增使用者
*/
@Insert("INSERT INTO user VALUES (NULL, #{username}, #{birthday}, #{sex}, #{address});")
void addUser(User user);
小結
註解開發的步驟
- 在介面中新增一個方法
- 給方法配置註解
- 在註解中寫SQL語句
- 測試
15.獲取新增主鍵值@SelectKey
目標
使用註解方式獲取新增資料後的主鍵
方式一
<insert id="addUser2" parameterType="user">
INSERT INTO user (username, birthday, sex, address) VALUES (#{username}, #{birthday}, #{sex}, #{address});
<selectKey resultType="int" keyColumn="id" keyProperty="id">
SELECT last_insert_id();
</selectKey>
</insert>
方式二
屬性 | 說明 |
---|---|
statement | 要執行的SQL語句:select last_insert_id() |
keyProperty | 實體類中主鍵的屬性 |
keyColumn | 表中主鍵的列名 |
resultType | 主鍵的資料型別 |
before | false 表示after,true表示before |
/*
新增使用者
*/
@Insert("INSERT INTO user VALUES (NULL, #{username}, #{birthday}, #{sex}, #{address});")
@SelectKey(statement = "SELECT LAST_INSERT_ID();", keyColumn = "id", keyProperty = "id", resultType = int.class, before = false)
void addUser(User user);
Mybatis註解小結
在註解方式實現基本CRUD操作中,使用的註解有:
註解 | 描述 |
---|---|
@Select | 配置查詢的SQL語句 |
@Results | 對查詢的結果進行對映相當於resultMap標籤 |
@Result | 對一個欄位進行對映 |
@Update | 配置修改的SQL語句 |
@Delete | 配置刪除的SQL語句 |
@Insert | 配置新增的SQL語句 |
@SelectKey | 獲取自增主鍵 |
16.註解實現:
一對一關聯查詢
MyBatis框架中除了使用XML配置檔案實現關係對映之外,也可以使用註解實現複雜的關係對映(一對一關聯查詢,一對多關聯查詢)。
複雜關係對映註解介紹
註解 | 描述 | 對應xml配置標籤 |
---|---|---|
@One | 用於一對一關聯對映 | association |
@Many | 用於一對多的關聯對映 | collection |
介面
public interface UserMapper {
/**
通過id查詢1個使用者
*/
User findUserById(int id);
/**
通過id查詢1個使用者擴充套件資訊,1對1
*/
UserInfo findUserInfoById(int id);
/**
通過userId查詢這個使用者所有的訂單資訊,1對多
*/
List<OrderForm> findOrdersByUserId(int userId);
}
查詢1個使用者資料,並且採用延遲載入關聯查詢出使用者擴充套件資料
-
編寫方法:通過id查詢使用者擴充套件資訊
- 方法名:findUserInfoById
- 使用@Select註解編寫SQL語句
-
編寫方法:通過id查詢1個使用者
- 方法名:findUserById
- @Select編寫查詢
- @Results配置1對1關聯對映
public interface UserMapper {
// 通過uid查詢使用者和擴充套件資訊
@Select("SELECT * FROM user WHERE id=#{uid}")
@Results({
@Result(property = "id", column = "id", id = true), // 主鍵對映
@Result(property = "userInfo", column = "id", javaType = UserInfo.class,
// select表示要查詢的方法名 fetchType指定為LAZY表示延遲載入
one = @One(select = "findUserInfoById", fetchType = FetchType.LAZY))
})
User findUserById(int uid);
// 通過uid查詢使用者和擴充套件資訊
@Select("SELECT * FROM user_info WHERE id=#{uid}")
UserInfo findUserInfoById(int uid);
}
一對多關聯查詢
關聯查詢出1號使用者全部訂單資料
erMapper介面
-
通過user_id查詢當前使用者訂單的方法
- 編寫findOrdersByUserId方法
- 使用@Select註解
-
修改findUserById()方法,增加1對多延遲載入配置
介面
public interface UserMapper {
/**
通過id查詢1個使用者
*/
@Select("select * from user where id=#{id}")
@Results({
@Result(column = "id", property = "id", id = true), //主鍵對映
// 一對一的配置
@Result(column = "id", property = "userInfo",
//select表示要查詢的方法名 fetchType指定為LAZY表示延遲載入
one = @One(select = "findUserInfoById", fetchType = FetchType.LAZY)),
//一對多的配置
@Result(column = "id", property = "orders",
many = @Many(select = "findOrdersByUserId", fetchType = FetchType.LAZY))
})
User findUserById(int id);
/**
通過id查詢1個使用者擴充套件資訊,1對1
*/
@Select("select * from user_info where id=#{id}")
UserInfo findUserInfoById(int id);
/**
通過userId查詢這個使用者所有的訂單資訊,1對多
*/
@Select("select * from order_form where user_id=#{id}")
@Results({
@Result(column = "user_id", property = "userId")
})
List<OrderForm> findOrdersByUserId(int userId);
}
小結
懶載入在不需要的時候就不去查詢,需要的時候就去查詢
17.學習總結
- Mybatis的入門配置
- Mybatis的CRUD
- Mybatis的關聯查詢
- 註解開發
- 註解關聯查詢