MyBatis
官網(wǎng):https://mybatis.org/mybatis-3/zh/index.html
環(huán)境:
- JDK1.8(盡量)
- MySQL - 5.7(超經(jīng)典)
- maven - 3.6.3
- Eclipse
回顧:
- JDBC
- MySQL
- Java基礎(chǔ)
- maven
- Junit
框架:配置文件、最好的方式:官網(wǎng)文檔
SSM框架:Spring SpringMVC Mybatis
1.簡介
1.1什么是Mybatis
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BMmIzH2v-1690204448185)(MyBatis.assets/image-20210113203554906.png)]
- MyBatis 是一款優(yōu)秀的持久層框架
- 它支持自定義 SQL、存儲過程以及高級映射
- MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。
- MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對象)為數(shù)據(jù)庫中的記錄。
- MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了[google code](https://baike.baidu.com/item/google code/2346604),并且改名為MyBatis 。2013年11月遷移到Github。
如何獲得Mybatis
- maven倉庫
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
- github - https://github.com/mybatis/mybatis-3/releases
- 中文文檔 - https://mybatis.org/mybatis-3/zh/index.html
1.2持久化
數(shù)據(jù)持久化
- 持久化,就是將程序的數(shù)據(jù)在持久狀態(tài)和瞬時狀態(tài)轉(zhuǎn)化的過程
- 內(nèi)存:斷電即失
- 數(shù)據(jù)庫(JDBC)、IO文件持久化
- 生活:冷藏(吃的時候再解凍)、罐頭
為什么需要持久化?
- 有一些對象,不能讓他丟失
- 內(nèi)存,太貴了
1.3持久層
Dao層、Service層、Controller層
什么叫持久層?
- 完成持久化工作的代碼塊
- 層的
- 界限十分明顯
1.4為什么需要Mybatis
- 幫助程序員將數(shù)據(jù)存入數(shù)據(jù)庫
- 傳統(tǒng)的JDBC過于復(fù)雜、簡化、框架、自動化
- 不用也行
最重要的一點:使用的人超級多
2.第一個Mybatis程序
思路:搭建環(huán)境 - 導(dǎo)入Mybatis - 編寫代碼 - 測試
全部文件:
mybatis-config.xml(會變)
MybatisUtil.java(不會變)
User.java(操作的表只要是user
,就不會改變)
UserDao.java(接口)
UserMapper.xml(會變)
UserDaoTest.java(小部分改變)
2.1搭建環(huán)境
2.1.1.搭建數(shù)據(jù)庫:
(想項目運行成功,一定保證數(shù)據(jù)庫正常連接?。?/p>
CREATE DATABASE `mybatis`;
use `mybatis`;
CREATE TABLE `user` (
`id` INT(20) NOT NULL,
`name` VARCHAR(30) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`pwd` VARCHAR(30) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
INSERT INTO `user` (id,`name`,pwd) VALUES
(1,"陳雨晴",123456),(2,"付姍",123456789),(3,"馬雨雨",112233)
2.1.2.新建項目(工程)
第一步:新建一個普通的maven項目
-
第一步:
-
第二步:刪除項目中的 src 文件夾,(作為父工程)
2.1.3導(dǎo)入依賴
pom.xml
<!-- mysql依賴 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<!--mybatis依賴 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
2.2創(chuàng)建一個模塊
第一步:創(chuàng)建Maven模塊
第二步:
2.2.1.編寫Mybatis的核心配置文件
在 src/main/resouce/mybatis-config.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSl=true&useUnicode=true&characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
</configuration>
2.2.2.編寫Mybatis的工具類
//sqlSessionFactory - sqlSession
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;// 提升作用域
static {
try {
// 使用mybatis第一步:獲取sqlSessionFactory對象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
2.3編寫代碼
2.3.1實體類
和mybatis/user
表一一對應(yīng)的實體類
package com.CYQ.pojo;
public class User {
private int id;
private String name;
private String pwd;
public User() {
super();
}
public User(int id, String name, String pwd) {
super();
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", pwd=" + pwd + "]";
}
}
2.3.2Dao接口
public interface UserDao {
List<User> getUserList();
}
2.3.3接口實現(xiàn)類
由原來UserDaoImpl轉(zhuǎn)換為一個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=綁定一個對應(yīng)的Dao/Mapper接口 -->
<mapper namespace="com.CYQ.dao.UserDao">
<!-- select查詢語句 -->
<select id="getUserList" resultType="com.CYQ.pojo.User">
select * from mybatis.user;
</select>
</mapper>
2.3.4.配置Mapper
在mybatis-config.xml中進行配置
<!-- 每一個Mapper.xml都需要在mybatis-config的核心配置文件中注冊?。?! -->
<mappers>
<mapper resource="com/CYQ/dao/UserMapper.xml"></mapper>
</mappers>
2.4測試
- junit
public class UserDaoTest {
@Test
public void test() {
//第一步:獲取sqlSession對象
SqlSession sqlSession = MybatisUtil.getSqlSession();
//方式一:getMapper
UserDao userDao = sqlSession.getMapper(UserDao.class);//得到接口
List<User> userList = userDao.getUserList();//得到接口內(nèi)的方法
for (User user : userList) {
System.out.println(user);
}
//關(guān)閉sqlSession
sqlSession.close();
}
}
2.5可能出現(xiàn)的問題
注意點:
出現(xiàn)異常:問題常出現(xiàn)在 -
1.查看UserDao的實現(xiàn)類UserMapper.xml問題
2.是否在mybatis-config.xml中配置
具體:
1.配置文件沒有注冊(mybatis-config.xml的問題)
2.綁定接口錯誤(UserMapper.xml的問題)
3.方法名稱不對(UserMapper.xml的問題)
4.返回類型不對(UserMapper.xml的問題)
所有的操作,均和接口(UserMapper.xml)和配置文件(Mybatis-config.xml)有關(guān)系
3.CRUD
mybatis-config.xml
<mapper namespace="com.CYQ.dao.UserMapper">
<!-- select查詢語句 -->
<select id="getUserList" resultType="com.CYQ.pojo.User">
select * from mybatis.user;
</select>
</mapper>
3.1namespace
namespace的包名要和接口(Dao/Mapper)的名字一致
3.2增刪改查
選擇:查詢語句
id
:就是對應(yīng)的namespace
中對應(yīng)的方法名
resultType
:Sql語句執(zhí)行的返回值!
parameterType
:參數(shù)的類型
步驟:
第一步:編寫接口
public interface UserMapper {
//查詢?nèi)坑脩?/span>
List<User> getUserList();
//根據(jù)id查詢用戶
User getUserById(int id);
//insert一個用戶
int addUser(User user);
//修改用戶
int updateUser(User user);
//刪除用戶
int deleteUser(int id);
}
第二步:編寫對應(yīng)的對應(yīng)的SQL語句
<mapper namespace="com.CYQ.dao.UserMapper">
<!-- select查詢語句 -->
<select id="getUserList" resultType="com.CYQ.pojo.User">
select * from mybatis.user;
</select>
<select id="getUserById" parameterType="int" resultType="com.CYQ.pojo.User">
select * from mybatis.user where id=#{id}
</select>
<!-- 對象中的屬性可以直接取出來 -->
<insert id="addUser" parameterType="com.CYQ.pojo.User">
insert into mybatis.user(id,name,pwd) values (#{id},#{name},#{pwd});
</insert>
<update id="updateUser" parameterType="com.CYQ.pojo.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id};
</update>
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#{id};
</delete>
</mapper>
第三步:測試
增刪改:一定需要提交事務(wù)
查:不需要提交事務(wù)
public class UserDaoTest {
//查詢
@Test
public void test() {
//第一步:獲取sqlSession對象
SqlSession sqlSession = MybatisUtil.getSqlSession();
//方式一:getMapper(推薦使用?。?/span>
UserMapper userDao = sqlSession.getMapper(UserMapper.class);//得到接口
List<User> userList = userDao.getUserList();
//方式二:(不推薦使用)
//List<Object> userList = sqlSession.selectList("com.CYQ.dao.UserDao.getUserList");
for (Object user : userList) {
System.out.println(user);
}
//關(guān)閉sqlSession
sqlSession.close();
}
//查詢
@Test
public void test01() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//獲得接口
User user = userMapper.getUserById(3);
System.out.println(user.toString());
sqlSession.close();
}
//增刪改 - 需要提交事務(wù)!??!
@Test
public void test02() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//獲得接口
userMapper.addUser(new User(4, "陳朋", "1995"));
//提交事務(wù):
sqlSession.commit();
//關(guān)閉sqlSession
sqlSession.close();
}
//修改
@Test
public void test03() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//獲得接口
userMapper.updateUser(new User(1,"陳雨晴","1997"));
//提交事務(wù):
sqlSession.commit();
//關(guān)閉sqlSession
sqlSession.close();
}
//刪除
@Test
public void test04() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//獲得接口
userMapper.deleteUser(4);
//提交事務(wù):
sqlSession.commit();
//關(guān)閉sqlSession
sqlSession.close();
}
}
3.3萬能Map
假設(shè),我們的實體類(或者數(shù)據(jù)庫中的表),屬性(或字段)過多,我們應(yīng)當考慮使用map!
map傳遞參數(shù),直接在sql中取出key即可;對象傳遞參數(shù),需要直接在sql中取對象的屬性。
只有一個基本參數(shù)的情況下,可以直接在sql中取到
多個參數(shù)用Map,或者注解!
對象和map的對比(認真對比)
UserMapper.xml
對象
<insert id="addUser" parameterType="com.CYQ.pojo.User">
insert into mybatis.user(id,name,pwd) values (#{id},#{name},#{pwd});
</insert>
map
<insert id="addUser2" parameterType="map">
insert into mybatis.user(id,name,pwd) values (#{userId},#{userName},#{password});
</insert>
UserMapperTest.java
對象
@Test
public void test02() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//獲得接口
userMapper.addUser(new User(4, "陳朋", "1995"));
//提交事務(wù):
sqlSession.commit();
//關(guān)閉sqlSession
sqlSession.close();
}
map
//增加
@Test
public void test002() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//獲得接口
HashMap<String,Object> map = new HashMap<String, Object>();
map.put("userId", 4);
map.put("userName", "楊帆");
map.put("password", "1996");
userMapper.addUser2(map);
//提交事務(wù):
sqlSession.commit();
//關(guān)閉sqlSession
sqlSession.close();
}
3.4模糊查詢
模糊查詢:一定要防止sql注入的問題
防止SLQ注入的寫法,在業(yè)務(wù)中使用多?。?!
第一步:接口
public interface UserMapper {
//查詢?nèi)坑脩? List<User> getUserLike();
}
第二步:SQL
<select id="getUserById" resultType="com.CYQ.pojo.User">
select * from mybatis.user where name like #{value}
</select>
<!--有效防止sql注入的寫法-->
<select id="getUserById" resultType="com.CYQ.pojo.User">
select * from mybatis.user where name like "%"#{value}"%"
</select>
第三步:測試
@Test
public void test01() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//獲得接口
List<User> userList = userMapper.getUserLike("%陳%");
for (Object user : userList) {
System.out.println(user);
}
sqlSession.close();
}
//防止sql注入
@Test
public void test01() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//獲得接口
List<User> userList = userMapper.getUserLike("陳");
for (Object user : userList) {
System.out.println(user);
}
sqlSession.close();
}
4.配置解析
4.1核心配置文件
- mybatis-config.xml
- MyBatis 的配置文件包含了會深深影響 MyBatis 行為的設(shè)置和屬性信息
configuration(配置)
- properties(屬性)
- settings(設(shè)置)
- typeAliases(類型別名)
- typeHandlers(類型處理器)
- objectFactory(對象工廠)
- plugins(插件)
-
environments(環(huán)境配置)
- environment(環(huán)境變量)
- transactionManager(事務(wù)管理器)
- dataSource(數(shù)據(jù)源)
- environment(環(huán)境變量)
- databaseIdProvider(數(shù)據(jù)庫廠商標識)
- mappers(映射器)
4.2環(huán)境配置(environments)
- MyBatis 可以配置成適應(yīng)多種環(huán)境
- 不過要記住:盡管可以配置多個環(huán)境,但每個 SqlSessionFactory 實例只能選擇一種環(huán)境。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSl=true&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
事務(wù)管理器:transactionManager
的type:JDBC和MANAGED兩種
數(shù)據(jù)源:dataSource
的type:UNPOOLED/POOLED/JNDI
Mybatis默認的事務(wù)管理器是:JDBC,連接池:POOLED
4.3屬性(Properties)
我們可通過properties屬性來實現(xiàn)引用配置文件
這些屬性可以在外部配置,并可以進行動態(tài)替換。既可以在典型的 Java 屬性文件中配置,也可以在 properties 元素的子元素中設(shè)置【db.properties】
4.3.1編寫配置文件
位置:src/main/resources/db.properties
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis?useSSl=true&useUnicode=true&characterEncoding=utf8
username = root
password = 123456
4.3.2在核心配置文件mybatis-config.xml中引入
<!-- 引入外部配置文件 -->
<properties resource="db.properties" >
<property name="username" value="root"/>
<property name="password" value="1233456"/>
</properties>
兩種方式:1.直接引入配置文件 2.在中添加標簽。
? 如果兩個配置矛盾,優(yōu)先使用配置文件中的。
環(huán)境配置可更改為:
<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>
4.4類型別名(typeAliases)
-
類型別名可為 Java 類型設(shè)置一個縮寫名字
-
存在的意義:減少類完全限定名的冗余
第一步:修改mybatis-config.xml
<!-- 可以給實體類起別名 -->
<typeAliases>
<typeAlias type="com.CYQ.pojo.User" alias="User"/>
</typeAliases>
<!-- 掃描實體類的包,默認別名為類名的首字母小寫 -->
<typeAliases>
<package name="com.CYQ.pojo"/>
</typeAliases>
第二步:修改UserMapper.xml
<select id="getUserList" resultType="User">
select * from mybatis.user;
</select>
<!--大寫也可以,即:“user”="User"-->
<select id="getUserList" resultType="user">
select * from mybatis.user;
</select>
兩種方式:
-
typeAlias
-
package
實體類比較少的時候,使用第一種;實體類比較多的時候,使用第二種
第一種可以自定義別名;第二種不可以自定義別名,但是可以通過注解自定義別名。
4.5設(shè)置(settings)
- 這是 MyBatis 中極為重要的調(diào)整設(shè)置,它們會改變 MyBatis 的運行時行為。
4.6映射器(mappers)
(推薦)方式一:通過***.xml文件
<!-- 每一個Mapper.xml都需要在mybatis的核心配置文件中注冊?。?! -->
<mappers>
<mapper resource="com/CYQ/dao/UserMapper.xml"></mapper>
</mappers>
方式二:通過class文件
<mappers>
<mapper class="com.CYQ.dao.UserMapper"/>
</mappers>
注意點:
- 接口和它的Mapper配置文件必須同名
- 接口和它的Mapper配置文件必須在同一個包下
4.7其他配置
- typeHandlers(類型處理器)
- objectFactory(對象工廠)
- plugins(插件)
- mybatis-genetator-core
- mybatis-plus
- 通用mapper
4.8生命周期和作用域
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-F1QZofHV-1690204448188)(MyBatis.assets/image-20210115155310926.png)]
生命周期和作用域,是至關(guān)重要的,因為錯誤的使用會導(dǎo)致非常嚴重的并發(fā)問題
SqlSessionFactoryBuilder
- 一旦創(chuàng)建了SqlSessionFactory,就不再需要了
- 局部變量
SqlSessionFactory
-
想象成:數(shù)據(jù)庫連接池
-
一旦創(chuàng)建就一直存在,沒有任何理由丟棄它或重新創(chuàng)建另一個實例
-
最佳作用域:應(yīng)用作用域
-
最簡單的就是使用單例模式或者靜態(tài)單例模式
SqlSession
-
連接到連接池的一個請求
-
SqlSession的實例不是線程安全的,因此是不能被共享的,所以最佳作用域:請求/方法作用域
-
需要關(guān)閉,否則資源被占用!
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-45erbNyG-1690204448189)(MyBatis.assets/image-20210115160635011.png)]
這里的每一個Mapper,就代表一個具體的業(yè)務(wù)
5.屬性名和字段名不一致
例子見:Mybatis-03 Module
5.1問題
新建一個項目,拷貝之前的,測試實體類字段不一致的情況
數(shù)據(jù)庫結(jié)構(gòu):
數(shù)據(jù)庫結(jié)構(gòu):
mybatis(數(shù)據(jù)庫)
user(表)
id(字段)
name(字段)
pwd(字段)
實體類構(gòu)造:構(gòu)造類的屬性和字段不對應(yīng)
public class User {
private int id;
private String name;
private String password;
...
}
測試代碼:
@Test
public void getUserById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 獲得接口
User user = userMapper.getUserById(5);
System.out.println(user.toString());
sqlSession.close();
}
測試出現(xiàn)問題:查不出來pwd
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MUDoEdO4-1690204448189)(MyBatis.assets/image-20210115190327962.png)]
5.2resultMap
結(jié)果集映射:
id name pwd
id name pasword
<mapper namespace="com.CYQ.dao.UserMapper">
<!-- 結(jié)果集映射 -->
<resultMap type="User" id="userMap">
<!-- column-數(shù)據(jù)庫中的字段 property-實體類中的屬性 -->
<result column="id" property="id" />
<result column="name" property="name" />
<result column="pwd" property="password" />
</resultMap>
<select id="getUserById" resultMap="userMap">
select * from user where id=#{id}
</select>
</mapper>
-
resultMap
元素是 MyBatis 中最重要最強大的元素。 -
ResultMap 的設(shè)計思想是:對簡單的語句做到零配置,對于復(fù)雜一點的語句,只需要描述語句之間的關(guān)系。
5.3解決方法
1.起別名:
<select id="getUserById" parameterType="int" resultType="User">
select id,name,pwd as password from mybatis.user where id=#{id}
</select>
2.結(jié)果集映射
<mapper namespace="com.CYQ.dao.UserMapper">
<!-- 結(jié)果集映射 -->
<resultMap type="User" id="userMap">
<!-- column-數(shù)據(jù)庫中的字段 property-實體類中的屬性 -->
<result column="id" property="id" />
<result column="name" property="name" />
<result column="pwd" property="password" />
</resultMap>
<select id="getUserById" resultMap="userMap">
select * from user where id=#{id}
</select>
</mapper>
6.日志
6.1日志工廠
如果一個數(shù)據(jù)庫操作出現(xiàn)異常,我們需要排錯。日志就是最好的助手!
曾經(jīng):sout,dubug
現(xiàn)在:日志工廠
Mybatis中,包含的種類:
-
SLF4J
-
LOG4J 【掌握】
-
LOG4J2
-
JDK_LOGGING
-
COMMONS_LOGGING
-
STDOUT_LOGGING【掌握】
-
NO_LOGGING
在Mybatis中,具體使用哪個日志實現(xiàn),在設(shè)置中實現(xiàn)
<settings>
<!-- 配置日志工廠 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
STDOUT_LOGGING - 為標準日志輸出
結(jié)果顯示:
6.2LOG4J
什么是log4J
- Log4j是Apache的一個開源項目
- 可以控制日志信息輸送的目的地是控制臺、文件、GUI組件,甚至是套接口服務(wù)器、NT的事件記錄器、UNIX Syslog守護進程等
- 可以控制每一條日志的輸出格式
- 通過一個配置文件來靈活地進行配置,而不需要修改應(yīng)用的代碼
第一步:導(dǎo)入依賴
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
第二步:配置properties文件
log4j.properties
#將等級為DEBUG的日志信息輸出到console和file這兩個目的地,console和file的定義在下面的代碼
log4j.rootLogger=DEBUG,console,file
#控制臺輸出的相關(guān)設(shè)置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件輸出的相關(guān)設(shè)置
log4j.appender.file = org.apache.log4j.RollingFileAppender
#日志文件生成位置,可以自定義
log4j.appender.file.File=./log/CYQ.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd HH:mm:ss}][%c]%m%n
#日志輸出級別
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
第三步:配置log4J為日志工廠實現(xiàn)
<settings>
<!-- 配置LOG4J實現(xiàn) -->
<setting name="logImpl" value="LOG4J"/>
</settings>
第四步:測試使用
直接junit測試UserMapperTest.java
6.3LOG4J簡單使用
第一步:導(dǎo)包(一定是log4j的Logger)
import org.apache.log4j.Logger;
第二步:日志對象,參數(shù)為當前類的class
static Logger logger = Logger.getLogger(UserDaoTest.class);
第三步:日志級別
@Test
public void testLog4j() {
logger.info("info:進入了testLog4j方法");
logger.debug("debug:進入了testLog4j方法");
logger.error("error:");
}
7.分頁
思考:為什么要分頁?
- 減少數(shù)據(jù)的處理量
7.1使用Limit分頁
SELECT * FROM user limit startindex,pagesize
SELECT * FROM user limit 3;--[0,3]
使用Mybatis實現(xiàn)分頁?。ê诵模篠QL)
1.接口
public interface UserMapper {
//Mybatis實現(xiàn)分頁
List<User> getUserByLimit(Map<String, Integer> map);
}
2.UserMapper.xml
<!-- Limit分頁 -->
<select id="getUserByLimit" parameterType="map"
resultMap="userMap">
SELECT * FROM user limit #{startIndex},#{pageSize}
</select>
3.測試
@Test
public void getUserByLimit() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
HashMap<String,Integer> map = new HashMap<String, Integer>();
map.put("startIndex", 0);
map.put("pageSize", 2);
List<User> users = userMapper.getUserByLimit(map);
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
7.2 RowBounds分頁
不再使用SQL實現(xiàn)分頁
1.接口:
public interface UserMapper {
//rouBounds實現(xiàn)分頁
List<User> getUserByRowBounds();
}
2.UserMapper.xml
<!-- RowBounds分頁 -->
<select id="getUserByRowBounds" resultMap="userMap">
SELECT * FROM user
</select>
3.測試
@Test
public void getUserByRowBounds() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
//RowBounds實現(xiàn)
//每頁顯示兩個,從第二個對象開始
RowBounds rowBounds = new RowBounds(1,2);//底標從0開始
//通過java代碼實現(xiàn)分頁
List<Object> userList = sqlSession.selectList("com.CYQ.dao.UserMapper.getUserByRowBounds",null,rowBounds);
for (Object object : userList) {
System.out.println(object);
}
sqlSession.close();
}
7.3分頁插件(了解)
8.注解開發(fā)
Mybatis-04
8.1面向接口編程
- 大家之前都學過面向?qū)ο缶幊?,也學習過接口,但在真正的開發(fā)中,很多時候我們會選擇面向接口編程
- 根本原因 : 解耦 , 可拓展 , 提高復(fù)用 , 分層開發(fā)中 , 上層不用管具體的實現(xiàn) , 大家都遵守共同的標準 , 使得開發(fā)變得容易 , 規(guī)范性更好
- 在一個面向?qū)ο蟮南到y(tǒng)中,系統(tǒng)的各種功能是由許許多多的不同對象協(xié)作完成的。在這種情況下,各個對象內(nèi)部是如何實現(xiàn)自己的,對系統(tǒng)設(shè)計人員來講就不那么重要了;
- 而各個對象之間的協(xié)作關(guān)系則成為系統(tǒng)設(shè)計的關(guān)鍵。小到不同類之間的通信,大到各模塊之間的交互,在系統(tǒng)設(shè)計之初都是要著重考慮的,這也是系統(tǒng)設(shè)計的主要工作內(nèi)容。面向接口編程就是指按照這種思想來編程。
關(guān)于接口的理解
- 接口從更深層次的理解,應(yīng)是定義(規(guī)范,約束)與實現(xiàn)(名實分離的原則)的分離。
- 接口的本身反映了系統(tǒng)設(shè)計人員對系統(tǒng)的抽象理解。
- 接口應(yīng)有兩類:
-
- 第一類是對一個個體的抽象,它可對應(yīng)為一個抽象體(abstract class);
- 第二類是對一個個體某一方面的抽象,即形成一個抽象面(interface);
- 一個體有可能有多個抽象面。抽象體與抽象面是有區(qū)別的。
三個面向區(qū)別
- 面向?qū)ο笫侵?,我們考慮問題時,以對象為單位,考慮它的屬性及方法 .
- 面向過程是指,我們考慮問題時,以一個具體的流程(事務(wù)過程)為單位,考慮它的實現(xiàn) .
- 接口設(shè)計與非接口設(shè)計是針對復(fù)用技術(shù)而言的,與面向?qū)ο螅ㄟ^程)不是一個問題.更多的體現(xiàn)就是對系統(tǒng)整體的架構(gòu)
8.2使用注解開發(fā)
1.注解直接在接口上實現(xiàn):
public interface UserMapper {
@Select("select * from user")
List<User> getUsers();
}
2.在核心配置文件(mybatis-config.xml)中綁定接口
<!-- 綁定接口 -->
<mappers>
<mapper class="com.CYQ.dao.UserMapper"/>
</mappers>
3.測試
@Test
public void test() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.getUsers();
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
}
本質(zhì):反射機制實現(xiàn)
底層:動態(tài)代理
代理模式示意圖:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DoWoD8yc-1690204448192)(MyBatis.assets/image-20210116182759016.png)]
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-96BVGasS-1690204448192)(MyBatis.assets/image-20210116185705344.png)]
8.3CRUD
我們可以在工具類創(chuàng)建的時候,實現(xiàn)自動提交事務(wù)!
第一步:設(shè)置自動提交事務(wù)為true
在MybatisUtil.java中設(shè)置
public static SqlSession getSqlSession() {
//默認為false,我們設(shè)置為true,true - 代表自動提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);
return sqlSession;
}
第二步:接口
public interface UserMapper {
//方法存在多個參數(shù),所有的參數(shù)前面必須加上:@Param注解
@Select("select * from user where id=#{id}")
User getUserById(@Param("id")int id);
@Insert("insert into user (id,name,pwd) values (#{id},#{name},#{password})")
int addUser(User user);
@Update("update user set name=#{name},pwd=#{password} where id=#{id}")
int updateUser(User user);
@Delete("delete from user where id=#{id}")
int deleteUser(@Param("id")int id);
}
第三步:測試
public class UserDaoTest {
@Test
public void test() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// List<User> users = mapper.getUsers();
// User user = mapper.getUserById(4);
// mapper.addUser(new User(6,"汪蘇瀧","1989"));
mapper.updateUser(new User(5, "許嵩", "1987"));
sqlSession.close();
}
}
關(guān)于@Param()注解
1.基本類型的參數(shù),無論有多少個,每個都需要加
2.引用類型不用加
3.如果只有一個基本類型,可以忽略,但是建議大家寫上
4.我們在SQL中引用的,就是我們在@Param()中設(shè)定的屬性名!??!
#{},${}區(qū)別
- #{ }不存在sql注入的問題,但是${}存在
9.LomBok
9.1使用步驟:
第一步:安裝LomBok插件
具體步驟參考:安裝LomBok
第二步:在項目中導(dǎo)入lombok的jar包(Maven倉庫形式)
<!-- lombok - 此處導(dǎo)入的版本是使用人數(shù)最多的! -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
第三步:寫注解
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String password;
}
@Getter/@Setter
@FiledNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor/@RequiredArgsConstructor/@NoArgsConstructor
@Data
@Builder
@Singular
@Delegate
@value
@Accessors
@wither
@NonNull
@Cleanup
@Synchronized
@Log
@SneakyThrows
說明部分:
@Data:無參構(gòu)造/Getter&Setter/toString/hashCode/equals
@AllArgsConstructor:全參構(gòu)造
@NoArgsConstructor:無參構(gòu)造
9.2優(yōu)缺點
優(yōu)點:
- 提升開發(fā)效率
- 屬性做修改時,也簡化了維護這些屬性所生成的getter/setter方法等
缺點:
- 不支持多種參數(shù)構(gòu)造器的重載(可手動去添加)
- 雖省略了getter/setter,但降低了代碼的可讀性
10 多對一 處理
Mybatis-05
多對一:
- 多個學生,對應(yīng)一個老師
- 對于學生而言, 關(guān)聯(lián) 多個學生關(guān)聯(lián)一個老師【多對一】
- 對于老師二眼,集合 ,一個老師有很多學生【一對多】
創(chuàng)建相關(guān)表
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8;
INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老師');
CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8;
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小紅', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小張', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');
10.1測試環(huán)境搭建:
第一步:導(dǎo)入lombok
第二步:新建實體類:Teacher/Student
//實體類:學生
@Data
public class Student {
private int id;
private String name;
//學生需要關(guān)聯(lián)一個老師
private Teacher teacher;
}
//實體類:老師
@Data
public class Teacher {
private int id;
private String name;
}
第三步:編寫接口文件:TeacherMapper.java StudentMapper.java
? 編寫對應(yīng)xml文件:TeacherMapper.xml StudentMapper.xml
第四步:核心文件(mybatis-config.xml)中配置
第五步:測試
10.2按照查詢嵌套處理
StudentMapper.xml
<mapper namespace="com.CYQ.dao.StudentMapper">
<!-- 思路:
1.查詢所有的學生信息
2.根據(jù)查詢出來的學生的tid,尋找對應(yīng)的老師
-->
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap type="Student" id="StudentTeacher">
<result property="id" column="id" />
<result property="name" column="name" />
<!-- 復(fù)雜的屬性:我們需要單獨處理 對象:association 集合:collection-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher" />
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id=#{tid}
</select>
</mapper>
10.3按照結(jié)果嵌套處理(常用)
<mapper namespace="com.CYQ.dao.StudentMapper">
<!-- 按照結(jié)果嵌套處理 -->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname
from student s ,teacher t
where s.tid=t.id
</select>
<resultMap type="Student" id="StudentTeacher2">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
</mapper>
回顧MySQL多對一查詢方式
- 子查詢
- 聯(lián)表查詢
11.一對多處理
Mybatis-06
比如:一個老師擁有多個學生!
對于老師而言,就是一對多的關(guān)系!
11.1環(huán)境搭建:
第一步:導(dǎo)入lombok
第二步:新建實體類:Teacher/Student
//實體類:學生
@Data
public class Student {
private int id;
private String name;
private int tid;
}
//實體類:老師
@Data
public class Teacher {
private int id;
private String name;
// 一個老師有多個學生
private List<Student> students;
}
第三步:編寫接口文件:TeacherMapper.java StudentMapper.java
? 編寫對應(yīng)xml文件:TeacherMapper.xml StudentMapper.xml
第四步:核心文件(mybatis-config.xml)中配置
第五步:測試
11.2按照查詢嵌套處理
TeacherMapper.xml
<mappers>
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from teacher where id=#{tid}
</select>
<resultMap type="teacher" id="TeacherStudent2">
<collection property="students" javaType="ArrayList" ofType="Student" select="getStduentByTeacherId" column="id">
</collection>
</resultMap>
<select id="getStduentByTeacherId" resultType="Student">
select * from student where tid=#{id}
</select>
</mappers>
11.3按照結(jié)果嵌套處理(常用)
TeacherMapper.xml
<mapper namespace="com.CYQ.dao.TeacherMapper">
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid,s.name sname,t.name tname,t.id tid
from student s,teacher t
where s.tid=t.id and t.id=#{tid}
</select>
<resultMap type="Teacher" id="TeacherStudent">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
</mapper>
11.4小結(jié)
1.關(guān)聯(lián) - association 【多對一】
2.集合:collection 【一對多
3.javaType & ofType
- javaType:用來指定實體類中屬性的類型
- ofType:用來指定映射到List或者集合中的pojo類型 - 泛型中的約束類型
注意點:
- 保證sql的可讀性
- 注意【一對多】,【多對一】,屬性名和字段的問題
- 問題不好排查錯誤,建議使用日志
面試高頻:
- MySLQ 引擎
- InnoDB 底層原理
- 索引
- 索引優(yōu)化
12.動態(tài)SQL
Mybatis-07
什么是動態(tài)SQL:
? 動態(tài)SQL就是指根據(jù)不同的條件,生成不同的SQL語句
if
choose(when,otherwise)
trim(where,set)
foreach
12.1搭建環(huán)境
創(chuàng)建相關(guān)表
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客標題',
`author` VARCHAR(30) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '創(chuàng)建時間',
`views` INT(30) NOT NULL COMMENT '瀏覽量'
)ENGINE=INNODB DEFAULT CHARSET=utf8
第一步:導(dǎo)包文章來源:http://www.zghlxwxcb.cn/news/detail-605089.html
第二步:編寫實體類
@Data
public class Blog {
private String id;
private String title;
private String author;
private Date createTime;
private int views;
}
第三步:
編寫接口BlogMapper.java
ublic interface BlogMapper {
//插入數(shù)據(jù):
int addBlog(Blog blog);
}
編寫*Mapper.xml
<mapper namespace="com.CYQ.dao.BlogMapper">
<!-- ...-->
</mapper>
第四步:核心配置文件(mybatis-config.xml)中配置
<mappers>
<mapper class="com.CYQ.dao.BlogMapper"/>
</mappers>
第五步:測試
12.2 IF
BlogMapper.xml
<mapper>
<select id="queryBlogIf" parameterType="map" resultType="Blog">
select * from blog where 1=1
<if test="title!=null">
and title = #{title}
</if>
<if test="author!=null">
and author=#{author}
</if>
</select>
</mapper>
測試:
@Test
public void queryBlogIf() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put("title", "大娛樂家");
map.put("author", "汪蘇瀧");
List<Blog> blogs = mapper.queryBlogIf(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
12.3 choose(when,otherwise)
相當于case … switch …
<mapper>
<select id="queryBlogChoose" parameterType="map"
resultType="Blog">
select * from blog
<where>
<!--choose下的,只執(zhí)行一個,要么執(zhí)行when的,要么執(zhí)行otherwise的-->
<choose>
<when test="title!=null">
title = #{title}
</when>
<when test="author!=null">
and author=#{author}
</when>
<!--至少會執(zhí)行:otherwise內(nèi)部的-->
<otherwise>
and views=#{views}
</otherwise>
</choose>
</where>
</select>
</mapper>
12.4 trim(where,set)
where
<mapper>
<select id="queryBlogIf" parameterType="map" resultType="Blog">
select * from blog
<where>
<if test="title!=null">
and title = #{title}
</if>
<if test="author!=null">
and author=#{author}
</if>
</where>
</select>
</mapper>
set
<mapper>
<update id="updateBlog" parameterType="map">
update blog
<set>
<if test="title!=null">
title = #{title},
</if>
<if test="author!=null">
author=#{author}
</if>
</set>
where id=#{id}
</update>
</mapper>
所謂的動態(tài)SQL,本質(zhì)還是SQL語句,只是我們可以在sql層面,去執(zhí)行一個邏輯代碼
12.5 SQL片段
有時候,我們會將一些功能的 部分,提取出來,方便復(fù)用!
第一步:使用標簽,抽取出公共的部分
第二步:在需要使用sql的部分,使用標簽引用即可
<mapper namespace="com.CYQ.dao.BlogMapper">
<!-- 使用sql抽出公共的部分 -->
<sql id="if-title-author">
<if test="title!=null">
and title = #{title}
</if>
<if test="author!=null">
and author=#{author}
</if>
</sql>
<select id="queryBlogIf" parameterType="map" resultType="Blog">
select * from blog
<where>
<!-- 在需要使用sql的部分,使用include -->
<include refid="if-title-author"/>
</where>
</select>
</mapper>
注意:
- 最好基于單表,來定義SQL片段
- 標簽中不要存在標簽
- 中盡量只包含一些
12.6 foreach
select * from user where 1=1 and (id=1 or id=2 or id=3)
<select id="queryBlogForeach" parameterType="map" resultType="Blog">
select * from blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id=#{id}
</foreach>
</where>
</select>
測試:
@Test
public void queryBlogForeach() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap<Object, Object> map = new HashMap<Object, Object>();
int[] ids = {1,2,3};
map.put("ids", ids);
mapper.queryBlogForeach(map);
sqlSession.close();
}
動態(tài)SQL就是在拼接SQL語句,我們只要保證SQL的正確性,按照SQL的格式,去排列組合就可以了
建議:現(xiàn)在MySQL中寫出完整的SQL,再對應(yīng)的去修改成我們的動態(tài)SQL
13.緩存
13.1簡介
查詢 : 連接數(shù)據(jù)庫,耗資源
一次查詢的結(jié)果,暫存在可以直接取到的地方?。?! - 內(nèi)存 - 放在內(nèi)存中的這些數(shù)據(jù)就叫“緩存”
我們再次查詢相同的數(shù)據(jù)的時候,直接走“緩存”就可以,不用走數(shù)據(jù)庫
1、什么是緩存 [ Cache ]?
- 存在內(nèi)存中的臨時數(shù)據(jù)。
- 將用戶經(jīng)常查詢的數(shù)據(jù)放在緩存(內(nèi)存)中,用戶去查詢數(shù)據(jù)就不用從磁盤上(關(guān)系型數(shù)據(jù)庫數(shù)據(jù)文件)查詢,從緩存中查詢,從而提高查詢效率,解決了高并發(fā)系統(tǒng)的性能問題。
2、為什么使用緩存?
- 減少和數(shù)據(jù)庫的交互次數(shù),減少系統(tǒng)開銷,提高系統(tǒng)效率。
3、什么樣的數(shù)據(jù)能使用緩存?
- 經(jīng)常查詢并且不經(jīng)常改變的數(shù)據(jù)。
13.2Mybatis緩存
- MyBatis包含一個非常強大的查詢緩存特性,它可以非常方便地定制和配置緩存。緩存可以極大的提升查詢效率。
- MyBatis系統(tǒng)中默認定義了兩級緩存:一級緩存和二級緩存
-
- 默認情況下,只有一級緩存開啟。(SqlSession級別的緩存,也稱為本地緩存)
- 二級緩存需要手動開啟和配置,他是基于namespace級別的緩存。
- 為了提高擴展性,MyBatis定義了緩存接口Cache。我們可以通過實現(xiàn)Cache接口來自定義二級緩存
13.3一級緩存
一級緩存也叫本地緩存:
- 與數(shù)據(jù)庫同一次會話期間查詢到的數(shù)據(jù)會放在本地緩存中。
- 以后如果需要獲取相同的數(shù)據(jù),直接從緩存中拿,沒必須再去查詢數(shù)據(jù)庫;
測試步驟:
第一步:開啟日志 mybatis-config.xml
<settings>
<!-- 標準日志工廠 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
第二步:測試,在同一個Session中查詢兩次相同記錄
@Test
public void getUserById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(3);
System.out.println(user);
User user2 = mapper.getUserById(3);
System.out.println(user2);
System.out.println(user==user2);
sqlSession.close();
}
第三步:查看日志輸出
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LQNmyCsa-1690204448193)(MyBatis.assets/image-20210119123231303.png)]
緩存失效的情況
1.增刪改操作,可能會改變原來的數(shù)據(jù),所以必定會刷新緩存!
2.查詢不同的東西
3.查詢不同的***Mapper.xml
4.手動清理緩存
@Test
public void getUserById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(3);
System.out.println(user);
sqlSession.clearCache();//手動請理緩存
sqlSession.close();
}
小結(jié):一級緩存是默認開啟的,只在一次Sqlsession中有效,也就是拿到 連接到關(guān)閉 這個時間段內(nèi)的緩存!?。?/p>
一級緩存相當于map(或者說:一級緩存就是一個map)
13.4二級緩存
- 二級緩存也叫全局緩存,一級緩存作用域太低了,所以誕生了二級緩存
- 基于namespace級別的緩存,一個名稱空間,對應(yīng)一個二級緩存;
- 工作機制
-
- 一個會話查詢一條數(shù)據(jù),這個數(shù)據(jù)就會被放在當前會話的一級緩存中;
- 如果當前會話關(guān)閉了,這個會話對應(yīng)的一級緩存就沒了;但是我們想要的是,會話關(guān)閉了,一級緩存中的數(shù)據(jù)被保存到二級緩存中;
- 新的會話查詢信息,就可以從二級緩存中獲取內(nèi)容;
- 不同的mapper查出的數(shù)據(jù)會放在自己對應(yīng)的緩存(map)中;
第一步:開啟全局緩存 - mybatis-config.xml
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
第二步:在要使用二級緩存的***Mapper.xml中配置
<!-- 在*Mapper.xml中使用二級緩存 -->
<!-- 60s 512個 -->
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
<!--一般最簡單的寫法-->
<cache />
第三步:測試
實體類要記得序列化
小結(jié):
1.只要開啟了二級緩存,在同一個Mapper下就有效
2.所有的數(shù)據(jù)都會先放在一級緩存中
3.只有當會話提交或關(guān)閉的時候,才會提交到二級緩存
13.5緩存原理
先訪問二級緩存,再訪問一級緩存
13.6自定義緩存-ehcache
使用步驟:
第一步:導(dǎo)包
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
第二步:配置ehcache.xml文章來源地址http://www.zghlxwxcb.cn/news/detail-605089.html
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="./tmpdir/Tmp_EhCache"/>
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="cloud_user"
eternal="false"
maxElementsInMemory="5000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
到了這里,關(guān)于【計算機編程語言】JAVA-MyBatis(Eclipse)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!