【计算机编程语言】JAVA-MyBatis(Eclipse)

news2025/1/11 14:45:09

文章目录

  • MyBatis
    • 1.简介
      • 1.1什么是Mybatis
      • 1.2持久化
      • 1.3持久层
      • 1.4为什么需要Mybatis
    • 2.第一个Mybatis程序
      • 2.1搭建环境
        • 2.1.1.搭建数据库:
        • 2.1.2.新建项目(工程)
        • 2.1.3导入依赖
      • 2.2创建一个模块
        • 2.2.1.编写Mybatis的核心配置文件
        • 2.2.2.编写Mybatis的工具类
      • 2.3编写代码
        • 2.3.1实体类
        • 2.3.2Dao接口
        • 2.3.3接口实现类
        • 2.3.4.配置Mapper
      • 2.4测试
      • 2.5可能出现的问题
    • 3.CRUD
      • 3.1namespace
      • 3.2增删改查
      • 3.3万能Map
      • 3.4模糊查询
    • 4.配置解析
      • 4.1核心配置文件
      • 4.2环境配置(environments)
      • 4.3属性(Properties)
      • 4.4类型别名(typeAliases)
      • 4.5设置(settings)
      • 4.6映射器(mappers)
      • 4.7其他配置
      • 4.8生命周期和作用域
    • 5.属性名和字段名不一致
      • 5.1问题
      • 5.2resultMap
      • 5.3解决方法
    • 6.日志
      • 6.1日志工厂
      • 6.2LOG4J
      • 6.3LOG4J简单使用
    • 7.分页
      • 7.1使用Limit分页
      • 7.2 RowBounds分页
      • 7.3分页插件(了解)
    • 8.注解开发
      • 8.1面向接口编程
      • 8.2使用注解开发
      • 8.3CRUD
    • 9.LomBok
      • 9.1使用步骤:
      • 9.2优缺点
    • 10 多对一 处理
      • 10.1测试环境搭建:
      • 10.2按照查询嵌套处理
      • 10.3按照结果嵌套处理(常用)
    • 11.一对多处理
      • 11.1环境搭建:
      • 11.2按照查询嵌套处理
      • 11.3按照结果嵌套处理(常用)
      • 11.4小结
    • 12.动态SQL
      • 12.1搭建环境
      • 12.2 IF
      • 12.3 choose(when,otherwise)
      • 12.4 trim(where,set)
      • 12.5 SQL片段
      • 12.6 foreach
    • 13.缓存
      • 13.1简介
      • 13.2Mybatis缓存
      • 13.3一级缓存
      • 13.4二级缓存
      • 13.5缓存原理
      • 13.6自定义缓存-ehcache

MyBatis

官网:https://mybatis.org/mybatis-3/zh/index.html

环境:

  • JDK1.8(尽量)
  • MySQL - 5.7(超经典)
  • maven - 3.6.3
  • Eclipse

回顾:

  • JDBC
  • MySQL
  • Java基础
  • maven
  • Junit

框架:配置文件、最好的方式:官网文档

SSM框架:Spring SpringMVC Mybatis

1.简介

1.1什么是Mybatis

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BMmIzH2v-1690204448185)(MyBatis.assets/image-20210113203554906.png)]

  • MyBatis 是一款优秀的持久层框架
  • 它支持自定义 SQL、存储过程以及高级映射
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  • 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持久化

数据持久化

  • 持久化,就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
  • 数据库(JDBC)、IO文件持久化
  • 生活:冷藏(吃的时候再解冻)、罐头

为什么需要持久化?

  • 有一些对象,不能让他丢失
  • 内存,太贵了

1.3持久层

Dao层、Service层、Controller层

什么叫持久层?

  • 完成持久化工作的代码块
  • 层的
  • 界限十分明显

1.4为什么需要Mybatis

  • 帮助程序员将数据存入数据库
  • 传统的JDBC过于复杂、简化、框架、自动化
  • 不用也行

最重要的一点:使用的人超级多

2.第一个Mybatis程序

思路:搭建环境 - 导入Mybatis - 编写代码 - 测试

全部文件:

mybatis-config.xml(会变)

MybatisUtil.java(不会变)

User.java(操作的表只要是user,就不会改变)

UserDao.java(接口)

UserMapper.xml(会变)

UserDaoTest.java(小部分改变)

2.1搭建环境

2.1.1.搭建数据库:

想项目运行成功,一定保证数据库正常连接!)

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导入依赖

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创建一个模块

第一步:创建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&amp;useUnicode=true&amp;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 表一一对应的实体类

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接口实现类

由原来UserDaoImpl转换为一个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接口 -->
<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();//得到接口内的方法
		
		for (User user : userList) {
			System.out.println(user);
		}		
		//关闭sqlSession
		sqlSession.close();	
	}
}

2.5可能出现的问题

注意点:

出现异常:问题常出现在 -

1.查看UserDao的实现类UserMapper.xml问题

2.是否在mybatis-config.xml中配置

具体:

1.配置文件没有注册(mybatis-config.xml的问题)

2.绑定接口错误(UserMapper.xml的问题)

3.方法名称不对(UserMapper.xml的问题)

4.返回类型不对(UserMapper.xml的问题)

所有的操作,均和接口(UserMapper.xml)和配置文件(Mybatis-config.xml)有关系

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:就是对应的namespace中对应的方法名

resultType:Sql语句执行的返回值!

parameterType:参数的类型

步骤:

第一步:编写接口

public interface UserMapper {
	//查询全部用户
	List<User> getUserList();
	//根据id查询用户
	User getUserById(int id);
	//insert一个用户
	int addUser(User user);
	//修改用户
	int updateUser(User user);
	//删除用户
	int deleteUser(int id);
}

第二步:编写对应的对应的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>

第三步:测试

增删改:一定需要提交事务

查:不需要提交事务

public class UserDaoTest {
	//查询
	@Test
	public void test() {
		//第一步:获取sqlSession对象
		SqlSession sqlSession = MybatisUtil.getSqlSession();
		
		//方式一:getMapper(推荐使用!)
		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);
		}		
		//关闭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();
	}
	
	//增删改 - 需要提交事务!!!
	@Test
	public void test02() {
		SqlSession sqlSession = MybatisUtil.getSqlSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//获得接口
		userMapper.addUser(new User(4, "陈朋", "1995"));
		//提交事务:
		sqlSession.commit();
		//关闭sqlSession
		sqlSession.close();
	}
	
	//修改
	@Test
	public void test03() {
		SqlSession sqlSession = MybatisUtil.getSqlSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//获得接口
		
		userMapper.updateUser(new User(1,"陈雨晴","1997"));
		
		//提交事务:
		sqlSession.commit();
		//关闭sqlSession
		sqlSession.close();
	}
	
	//删除
	@Test
	public void test04() {
		SqlSession sqlSession = MybatisUtil.getSqlSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//获得接口
		
		userMapper.deleteUser(4);
		
		//提交事务:
		sqlSession.commit();
		//关闭sqlSession
		sqlSession.close();
	}
	
}

3.3万能Map

假设,我们的实体类(或者数据库中的表),属性(或字段)过多,我们应当考虑使用map!

map传递参数,直接在sql中取出key即可;对象传递参数,需要直接在sql中取对象的属性

只有一个基本参数的情况下,可以直接在sql中取到

多个参数用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"));
		//提交事务:
		sqlSession.commit();
		//关闭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);
    //提交事务:
    sqlSession.commit();
    //关闭sqlSession
    sqlSession.close();
}

3.4模糊查询

模糊查询:一定要防止sql注入的问题

防止SLQ注入的写法,在业务中使用多!!!

第一步:接口

public interface UserMapper {
	//查询全部用户
	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 行为的设置和属性信息

configuration(配置)

  • properties(属性)
  • settings(设置)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境配置)
    • environment(环境变量)
      • transactionManager(事务管理器)
      • dataSource(数据源)
  • databaseIdProvider(数据库厂商标识)
  • mappers(映射器)

4.2环境配置(environments)

  • MyBatis 可以配置成适应多种环境
  • 不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
<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&amp;useUnicode=true&amp;characterEncoding=utf8"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </dataSource>
    </environment>		
</environments>

事务管理器transactionManager的type:JDBC和MANAGED两种

数据源dataSource的type:UNPOOLED/POOLED/JNDI

Mybatis默认的事务管理器是:JDBC,连接池:POOLED

4.3属性(Properties)

我们可通过properties属性来实现引用配置文件

这些属性可以在外部配置,并可以进行动态替换。既可以在典型的 Java 属性文件中配置,也可以在 properties 元素的子元素中设置【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.在中添加标签。

​ 如果两个配置矛盾,优先使用配置文件中的。

环境配置可更改为:

<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 类型设置一个缩写名字

  • 存在的意义:减少类完全限定名的冗余

第一步:修改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设置(settings)

  • 这是 MyBatis 中极为重要的调整设置,它们会改变 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生命周期和作用域

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F1QZofHV-1690204448188)(MyBatis.assets/image-20210115155310926.png)]

生命周期和作用域,是至关重要的,因为错误的使用会导致非常严重的并发问题

SqlSessionFactoryBuilder

  • 一旦创建了SqlSessionFactory,就不再需要了
  • 局部变量

SqlSessionFactory

  • 想象成:数据库连接池

  • 一旦创建就一直存在,没有任何理由丢弃它或重新创建另一个实例

  • 最佳作用域:应用作用域

  • 最简单的就是使用单例模式或者静态单例模式

SqlSession

  • 连接到连接池的一个请求

  • SqlSession的实例不是线程安全的,因此是不能被共享的,所以最佳作用域:请求/方法作用域

  • 需要关闭,否则资源被占用!

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-45erbNyG-1690204448189)(MyBatis.assets/image-20210115160635011.png)]

这里的每一个Mapper,就代表一个具体的业务

5.属性名和字段名不一致

例子见:Mybatis-03 Module

5.1问题

新建一个项目,拷贝之前的,测试实体类字段不一致的情况

数据库结构

数据库结构:
mybatis(数据库)
		user(表)
			id(字段)
			name(字段)
			pwd(字段)

实体类构造:构造类的属性和字段不对应

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();
}

测试出现问题:查不出来pwd

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MUDoEdO4-1690204448189)(MyBatis.assets/image-20210115190327962.png)]

5.2resultMap

结果集映射:

id	 name	 pwd
id 	 name    pasword
<mapper namespace="com.CYQ.dao.UserMapper">

	<!-- 结果集映射 -->
	<resultMap type="User" id="userMap">
		<!-- column-数据库中的字段 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 的设计思想是:对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系。

5.3解决方法

1.起别名:

<select id="getUserById" parameterType="int" resultType="User">
		select id,name,pwd as password from mybatis.user where id=#{id}
</select>

2.结果集映射

<mapper namespace="com.CYQ.dao.UserMapper">

	<!-- 结果集映射 -->
	<resultMap type="User" id="userMap">
		<!-- column-数据库中的字段 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日志工厂

如果一个数据库操作出现异常,我们需要排错。日志就是最好的助手!

曾经:sout,dubug

现在:日志工厂

在这里插入图片描述

Mybatis中,包含的种类:

  • SLF4J

  • LOG4J 【掌握】

  • LOG4J2

  • JDK_LOGGING

  • COMMONS_LOGGING

  • STDOUT_LOGGING【掌握】

  • NO_LOGGING

在Mybatis中,具体使用哪个日志实现,在设置中实现

<settings>
    <!-- 配置日志工厂 -->
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

STDOUT_LOGGING - 为标准日志输出

结果显示:

在这里插入图片描述

6.2LOG4J

什么是log4J

  • Log4j是Apache的一个开源项目
  • 可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等
  • 可以控制每一条日志的输出格式
  • 通过一个配置文件来灵活地进行配置,而不需要修改应用的代码

第一步:导入依赖

<!-- 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

#控制台输出的相关设置
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

#文件输出的相关设置
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为日志工厂实现

<settings>
    <!-- 配置LOG4J实现 -->
    <setting name="logImpl" value="LOG4J"/>
</settings>

第四步:测试使用

直接junit测试UserMapperTest.java

在这里插入图片描述

6.3LOG4J简单使用

第一步:导包(一定是log4j的Logger)

import org.apache.log4j.Logger;

第二步:日志对象,参数为当前类的class

static Logger logger = Logger.getLogger(UserDaoTest.class);

第三步:日志级别

@Test
public void testLog4j() {
    logger.info("info:进入了testLog4j方法");
    logger.debug("debug:进入了testLog4j方法");
    logger.error("error:");
}

7.分页

思考:为什么要分页?

  • 减少数据的处理量

7.1使用Limit分页

SELECT * FROM user limit startindex,pagesize

SELECT * FROM user limit 3;--[0,3]

使用Mybatis实现分页!(核心:SQL)

1.接口

public interface UserMapper {
    //Mybatis实现分页
    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实现分页

1.接口:

public interface UserMapper {
    //rouBounds实现分页
    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实现
    //每页显示两个,从第二个对象开始
    RowBounds rowBounds = new RowBounds(1,2);//底标从0开始

    //通过java代码实现分页
    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.注解开发

Mybatis-04

8.1面向接口编程

  • 大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程
  • 根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , 上层不用管具体的实现 , 大家都遵守共同的标准 , 使得开发变得容易 , 规范性更好
  • 在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;
  • 而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。

关于接口的理解

  • 接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。
  • 接口的本身反映了系统设计人员对系统的抽象理解。
  • 接口应有两类:
    • 第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class);
    • 第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface);
  • 一个体有可能有多个抽象面。抽象体与抽象面是有区别的。

三个面向区别

  • 面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法 .
  • 面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现 .
  • 接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题.更多的体现就是对系统整体的架构

8.2使用注解开发

1.注解直接在接口上实现

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();
}
}

本质:反射机制实现

底层:动态代理

代理模式示意图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DoWoD8yc-1690204448192)(MyBatis.assets/image-20210116182759016.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-96BVGasS-1690204448192)(MyBatis.assets/image-20210116185705344.png)]

8.3CRUD

我们可以在工具类创建的时候,实现自动提交事务!

第一步:设置自动提交事务为true

在MybatisUtil.java中设置

public static SqlSession getSqlSession() {
    //默认为false,我们设置为true,true - 代表自动提交
    SqlSession sqlSession = sqlSessionFactory.openSession(true);
    return sqlSession;
}

第二步:接口

public interface UserMapper {
	
	//方法存在多个参数,所有的参数前面必须加上:@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();
	}
}

关于@Param()注解

1.基本类型的参数,无论有多少个,每个都需要加

2.引用类型不用加

3.如果只有一个基本类型,可以忽略,但是建议大家写上

4.我们在SQL中引用的,就是我们在@Param()中设定的属性名!!!

#{},${}区别

  • #{ }不存在sql注入的问题,但是${}存在

9.LomBok

9.1使用步骤:

第一步:安装LomBok插件

具体步骤参考:安装LomBok

第二步:在项目中导入lombok的jar包(Maven仓库形式)

  <!-- lombok - 此处导入的版本是使用人数最多的! -->
<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:无参构造/Getter&Setter/toString/hashCode/equals

@AllArgsConstructor:全参构造

@NoArgsConstructor:无参构造

9.2优缺点

优点:

  • 提升开发效率
  • 属性做修改时,也简化了维护这些属性所生成的getter/setter方法等

缺点:

  • 不支持多种参数构造器的重载(可手动去添加)
  • 虽省略了getter/setter,但降低了代码的可读性

10 多对一 处理

Mybatis-05

多对一:

  • 多个学生,对应一个老师
  • 对于学生而言, 关联 多个学生关联一个老师【多对一】
  • 对于老师二眼,集合 ,一个老师有很多学生【一对多】

创建相关表

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测试环境搭建:

第一步:导入lombok

第二步:新建实体类:Teacher/Student

//实体类:学生
@Data
public class Student {
	private int id;
	private String name;	
	//学生需要关联一个老师
	private Teacher teacher;
}

//实体类:老师
@Data
public class Teacher {
	private int id;
	private String name;
}

第三步:编写接口文件:TeacherMapper.java StudentMapper.java

​ 编写对应xml文件:TeacherMapper.xml StudentMapper.xml

第四步:核心文件(mybatis-config.xml)中配置

第五步:测试

10.2按照查询嵌套处理

StudentMapper.xml

<mapper namespace="com.CYQ.dao.StudentMapper">

	<!-- 思路: 
	1.查询所有的学生信息 
	2.根据查询出来的学生的tid,寻找对应的老师 
	-->

	<select id="getStudent" resultMap="StudentTeacher">
		select * from student
	</select>

	<resultMap type="Student" id="StudentTeacher">
		<result property="id" column="id" />
		<result property="name" column="name" />
		<!-- 复杂的属性:我们需要单独处理  对象: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按照结果嵌套处理(常用)

<mapper namespace="com.CYQ.dao.StudentMapper">

	<!-- 按照结果嵌套处理 -->
	<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多对一查询方式

  • 子查询
  • 联表查询

11.一对多处理

Mybatis-06

比如:一个老师拥有多个学生!

对于老师而言,就是一对多的关系!

11.1环境搭建:

第一步:导入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

​ 编写对应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按照结果嵌套处理(常用)

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小结

1.关联 - association 【多对一】

2.集合:collection 【一对多

3.javaType & ofType

  • javaType:用来指定实体类中属性的类型
  • ofType:用来指定映射到List或者集合中的pojo类型 - 泛型中的约束类型

注意点:

  • 保证sql的可读性
  • 注意【一对多】,【多对一】,属性名和字段的问题
  • 问题不好排查错误,建议使用日志

面试高频

  • MySLQ 引擎
  • InnoDB 底层原理
  • 索引
  • 索引优化

12.动态SQL

Mybatis-07

什么是动态SQL

动态SQL就是指根据不同的条件,生成不同的SQL语句

if
choose(when,otherwise)
trim(where,set)
foreach

12.1搭建环境

创建相关表

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 '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8

第一步:导包

第二步:编写实体类

@Data
public class Blog {
	private String id;
	private String title;
	private String author;
	private Date createTime;
	private int views;
}

第三步:

编写接口BlogMapper.java

ublic interface BlogMapper {
	//插入数据:
	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下的,只执行一个,要么执行when的,要么执行otherwise的-->
			<choose>
				<when test="title!=null">
					title = #{title}
				</when>
				<when test="author!=null">
					and author=#{author}
				</when>
                <!--至少会执行:otherwise内部的-->
				<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>

所谓的动态SQL,本质还是SQL语句,只是我们可以在sql层面,去执行一个逻辑代码

12.5 SQL片段

有时候,我们会将一些功能的 部分,提取出来,方便复用!

第一步:使用标签,抽取出公共的部分

第二步:在需要使用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();
}

动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了

建议:现在MySQL中写出完整的SQL,再对应的去修改成我们的动态SQL

13.缓存

13.1简介

查询  :  连接数据库,耗资源
	一次查询的结果,暂存在可以直接取到的地方!!!	 - 内存   - 放在内存中的这些数据就叫“缓存”
	
	我们再次查询相同的数据的时候,直接走“缓存”就可以,不用走数据库

1、什么是缓存 [ Cache ]?

  • 存在内存中的临时数据。
  • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

2、为什么使用缓存?

  • 减少和数据库的交互次数,减少系统开销,提高系统效率。

3、什么样的数据能使用缓存?

  • 经常查询并且不经常改变的数据。

13.2Mybatis缓存

  • MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
  • MyBatis系统中默认定义了两级缓存:一级缓存二级缓存
    • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
    • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
    • 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

13.3一级缓存

一级缓存也叫本地缓存:

  • 与数据库同一次会话期间查询到的数据会放在本地缓存中。
  • 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;

测试步骤:

第一步:开启日志 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();
}

第三步:查看日志输出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LQNmyCsa-1690204448193)(MyBatis.assets/image-20210119123231303.png)]

缓存失效的情况

1.增删改操作,可能会改变原来的数据,所以必定会刷新缓存!

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();
}

小结:一级缓存是默认开启的,只在一次Sqlsession中有效,也就是拿到 连接到关闭 这个时间段内的缓存!!!

一级缓存相当于map(或者说:一级缓存就是一个map)

13.4二级缓存

  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
  • 工作机制
    • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
    • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
    • 新的会话查询信息,就可以从二级缓存中获取内容;
    • 不同的mapper查出的数据会放在自己对应的缓存(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 />

第三步:测试

实体类要记得序列化

小结:

1.只要开启了二级缓存,在同一个Mapper下就有效

2.所有的数据都会先放在一级缓存中

3.只有当会话提交或关闭的时候,才会提交到二级缓存

13.5缓存原理

先访问二级缓存,再访问一级缓存

13.6自定义缓存-ehcache

使用步骤:

第一步:导包

<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.1.0</version>
</dependency>

第二步:配置ehcache.xml

<?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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/787170.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux学成之路(基础篇(二十三)MySQL服务(下)

目录 MySQL服务之SQL语句 一、SQL语句类型 一、 DDL语句 二、DML语句 三、DCL语句 四、DQL 语句 二、 数据库操作 一、查看 二、创建 三、进入 四、删除数据库 五、更改数据库名称 六、更改字符集 三、数据表管理 一、数据类型 一、数值类型 TINYINT SMALLINT…

JUC并发编程之CompletableFuture详解

目录 1.Future接口 1.1 Future介绍 1.1.1 FutureTask 1.1.2 代码示例 2. CompletableFuture 2.1 基本概念 2.2 代码示例 2.2.1 创建CompletableFuture 2.2.2 函数式接口&#xff08;补充&#xff09; 2.2.3 异步任务组合 1.Future接口 1.1 Future介绍 JUC并发编程中的…

(三)InfluxDB入门(借助Web UI)

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 3 章 InfluxDB入门&#xff08;借助Web UI&#xff09; 借助Web UI&#xff0c;我们可以更好地理解InfluxD…

SiddonGpu编译过程记录

1. 还是想要能够快速生成DRR&#xff0c;用了这个up的代码GitHub - fabio86d/CUDA_DigitallyReconstructedRadiographs: GPU accelerated python library for generation of Digitally Reconstructed Radiographs (March 2018) 在看步骤的时候不是很清晰。尤其是procedure to…

生产环境Session解决方案、Session服务器之Redis

目录 一、服务器配置 二、安装nginx 三、安装配置Tomcat&#xff1a; 四、配置session Session服务器之Redis Redis与Memcached的区别 安装部署redis 一、服务器配置 IP地址 主机名 软件包列表 192.168.100.131 huyang1 nginx 192.168.100.133 huyang3 JDK Tomca…

隧道安全监测解决方案

隧道安全监测 解决方案 一、监测目的 通过监控量测&#xff0c;实现信息化施工&#xff0c;不仅能及时掌握隧道实际的地质情况&#xff0c;掌握隧道围岩、支护衬砌结构的受力特征和变形情况&#xff0c;据此可以尽早发现塌方、大变形等灾害征兆&#xff0c;及时采取措施&…

Qgis二次开发-加载高德在线地图失败报错Raster layer Cannot instantiate the ‘wms‘ data provider

1.加载在线的高德地图 以下是在线高德地图地址。 http://webrd01.is.autonavi.com/appmaptile?x{x}&y{y}&z{z}&langzh_cn&size1&scale1&style8 以下是代码示例&#xff1a; #include <QApplication> #include <QMainWindow> #include …

Django学习笔记-表单(forms)的使用

在Django中提供了了form表单&#xff0c;可以更为简单的创建表单模板信息&#xff0c;简化html的表单。 一、网页应用程序中表单的应用 表单通常用来作为提交数据时候使用。 1.1 创建表单模板文件夹 在项目文件夹下创建一个template文件夹&#xff0c;用于存储所有的html模…

Integer 和 int

一、区别 1.Integer是int的包装类&#xff0c;int则是java的一种基本的数据类型&#xff1b; 2.Integer变量必须实例化之后才能使用&#xff0c;而int变量不需要实例化&#xff1b; 3.Integer实际是对象的引用&#xff0c;当new一个Integer时&#xff0c;实际上生成一个指针指向…

Linux vsftp三种模式的简单配置部署

环境&#xff1a;Debian 6.1.27-1kali1 (2023-05-12) vsftpd 安装 --查看是否当前系统是否已安装 apt list --installed | grep vsftpd 没有安装的话&#xff0c;就正常安装 apt-get update apt-get install vsftpd 一、匿名用户模式 分享一些不重要文件&#xff0c;任…

AI学习笔记二:YOLOV5环境搭建及测试全过程

若该文为原创文章&#xff0c;转载请注明原文出处。 记录yolov5从环境搭建到测试全过程。 一、运行环境 1、系统&#xff1a;windows10 &#xff08;无cpu) 2、yolov5版本&#xff1a;yolov5-5.0 3、python版本&#xff1a;py3.8 在创建虚拟环境前需要先把miniconda3和py…

Font Awesome 5使用

Font Awesome 5介绍 Font Awesome 5 的专业版有7842个图标。 要使用免费的Font Awesome 5 图标&#xff0c;您可以选择下载Font Awesome库&#xff0c;或者在Font Awesome注册一个帐户&#xff0c;并获得一个代码&#xff08;称为KIT CODE&#xff09;&#xff0c;以便在将Fo…

Wireshark抓包分析教程(ubuntu版本)

安装 first&#xff0c;多亏我们的C知道&#xff0c;成功安装了wireshark&#xff0c; Steps are as following&#xff1a; 添加wireshark的软件源(PPA:personal package archive(档案)) sudo apt-add-repository ppa:wireshark-dev/stable ppa:wireshark-dev/stable 是一个…

Quad Remesher 参数效果记录

基本属性 Detect Hard-Edges by angle 这个属性最好开启&#xff0c;它用于保持必要的边缘

WEB:ics-06

背景知识 burpsuite的使用 题目 所有都尝试点了一遍&#xff0c;只有报表中心可以打开 先查看源代码&#xff0c;没有发现有用的信息 选择了日期范围但是毫无反应&#xff0c;这里发现url中有一个id1&#xff0c;尝试抓包爆破 使用bp进行抓包 设置有效载荷配置&#xff0c;开…

(链表) 剑指 Offer 24. 反转链表 ——【Leetcode每日一题】

❓剑指 Offer 24. 反转链表 难度&#xff1a;简单 定义一个函数&#xff0c;输入一个链表的头节点&#xff0c;反转该链表并输出反转后链表的头节点。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 限制&#xff1a; 0 < …

小程序如何删除/上架/下架商品

在小程序中&#xff0c;产品的删除、上架和下架是常见的操作&#xff0c;可以根据实际需求来管理商品的展示与销售。下面将介绍如何在小程序中删除上架下架商品的具体步骤。 进入商品管理页面&#xff0c; 在个人中心点击管理入口&#xff0c;然后找到“商品管理”菜单并点击。…

Git----分布式版本控制系统

1. 简介 Git是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或大或小的项目。它是世界上目前最先进的分布式版本控制系统。 Git是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源代码的版本控制软件。 Git与常用的版本控制工具CVS、Subversio…

2023最新版本Activiti7系列-流程中的任务

流程中的任务 1.用户任务 用户任务:用于定义流程中需要人工参与的任务。 用户任务可以在流程中创建并分配给特定的用户或用户组。当流程执行到用户任务时&#xff0c;流程将暂停&#xff0c;并等待相应的用户完成该任务。完成用户任务后&#xff0c;流程将继续执行。 用户任…

系统架构设计师视频教程笔记

根据历年真题倒翻官方教程&#xff0c;发现好多内容没有&#xff0c;据说2022新版改动很大 既然是真题&#xff0c;肯定有参考价值&#xff0c;那就看看旧视频吧 考试分享 软考高级架构师&#xff0c;有用但不大【通过后分享】 up主公司要接政府项目&#xff0c;有考证需求 …