首页 > 其他分享 >MyBatis

MyBatis

时间:2023-01-19 11:01:20浏览次数:69  
标签:缓存 name mybatis sqlSession user MyBatis id


1、简介

1.1、什么是MyBatis

  • MyBatis 是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架
  • MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
  • MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
  • MyBatis 本是apache的一个开源项目iBatis ,2010年这个项目由apache software foundation 迁移到了google code,并且改名为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>

1.2、持久化

数据持久化

  • 持久化就是将程序的数据在持久化状态和瞬时转化的状态
  • 数据库(jdbc),io文件持久化

为什么需要持久化?

  • 不能让数据丢失
  • 内存太贵了

1.3、持久层

Dao层,Service层,Controller层…

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

1.4、为什么需要MyBatis

  • 方便
  • 传统的JDBC代码太复杂,简化开发,自动化
  • 将数据存入到数据库中
  • 优点
  • 简单易学
  • 灵活
  • 解除sql与程序代码的耦合
  • 提供映射标签,支持对象与数据库的orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql

2、第一个MyBatis程序

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

2.1、搭建环境

  1. 搭建数据库
CREATE DATABASE mybatis;


USE mybati;


CREATE TABLE user1(
id int(20) not null primary key,
name VARCHAR(30) DEFAULT null,
pwd VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8



INSERT INTO user1 (id,name,pwd) VALUES
(1,"张三",111),
(2,"李四",222),
(3,"王五",333),
(4,"默辨",444);

新建项目:

  1. 新建一个普通得maven项目
  2. 删除src目录
  3. 导入maven依赖
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>


<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

2.2、创建一个模块

配置文件: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=UTF-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="pers/mobian/dao/UserMapper.xml"/>
</mappers>

</configuration>

编写mybatis工具类

package pers.mobian.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

//sqlSessionFactory
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;

static {
try {
//使用MybatisUtil获取sqilSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

} catch (Exception e) {
e.printStackTrace();
}
}

//既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。
// SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
public static SqlSession getSqlSession() {
// SqlSession sqlSession = sqlSessionFactory.openSession();
// return sqlSession;

return sqlSessionFactory.openSession();
}

2.3、编写代码

实体类

package pers.mobian.pojo;

public class User {
private int id;
private String name;
private String pwd;


public User() {
}

public User(int id, String name, String pwd) {
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;
}
}

Dao接口

package pers.mobian.dao;

import pers.mobian.pojo.User;

import java.util.List;

public interface UserDao {
List<User> getUserList();
}

接口实现类(由原来的UserDaoImpl类转化而来)

<?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="pers.mobian.pojo.User">
<!--select查询语句 resultType完全限定名-->
<select id="getUserList" resultType="pers.mobian.pojo.User">
select * from mybatis.user
</select>
</mapper>
package pers.mobian.dao;
import pers.mobian.pojo.User;
import java.util.List;
public class UserDaoImpl implements UserDao {
public List<User> getUserList() {
//执行SQL
String sql = "select * from mybatis.user";

// return 结果集 -->resultType
}
}

2.4、测试

特别注意这个错误:数据类型绑定有误

org.apache.ibatis.binding.BindingException: Type interface pers.mobian.dao.UserDao is not known to the MapperRegistry.

MapperRegistry:核心配置文件中的mappers

junit测试

package pers.mobian.dao;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import pers.mobian.pojo.User;
import pers.mobian.util.MybatisUtil;

import java.util.List;

public class UserDaoTest {
@Test
public void test() {
// 第一步:获得SqlSession对
SqlSession sqlSession = MybatisUtil.getSqlSession();

try {
// 方法一:getMapper(推荐使用)
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();

// 方法二:
// List<User> userList1 = sqlSession.selectList("pers.mobian.dao.UserDao.getUserList");

for (User user : userList) {
System.out.println(user.toString());
}

} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭SqlSession
sqlSession.close();
}
}
}

测试结果:

User{id=1, name='张三', pwd='111'}
User{id=2, name='李四', pwd='222'}
User{id=3, name='王五', pwd='333'}
User{id=4, name='默辨', pwd='444'}

可能会遇到的问题:

  • 配置文件没有注册
  • 绑定接口错误
  • 方法名不对
  • 返回类型不对
  • Maven导出资源问题
  • 标签匹配错误
  • resource绑定的mapper资源路径,需要使用/
  • 输出的xml文件中存在乱码问题

3、CRUD

3.1、namespace

namespace中的包名要和Dao/Mapper

3.2、select

选择,查询语句:

  • id:就是对应的namespace中的方法名
  • resultType:Sql语句执行的返回值
  • parameterType:参数类型

1、编写接口

//根据Id查询用户
List<User> getUserById(int id);

2、编写接口对象的mapper中的sql语句

<select id="getUserById" resultType="pers.mobian.pojo.User">
select * from mybatis.user where id=#{id}
</select>

3、测试

@Test
public void getUserById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
//仅仅只有这一句是执行sql的,其余三行不变
System.out.println(mapper.getUserById(1));
sqlSession.close();
}

3.3、delete

1、编写接口

//删除用户
int deleteUser(int id);

2、编写接口对象的mapper中的sql语句

<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#{id};
</delete>

3、测试

@Test
public void deleteUser() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
//执行对应的sql语句,且需要提交事务
mapper.deleteUser(1);
sqlSession.commit();

sqlSession.close();
}

3.4、update

1、编写接口

//修改用户
int updateUser(User user);

2、编写接口对象的mapper中的sql语句

<update id="updateUser" parameterType="pers.mobian.pojo.User">
update mybatis.user set id=#{id},name=#{name},pwd=#{pwd} where id=#{id};
</update>

3、测试

@Test
public void updateUser() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
//执行对应的sql语句,且需要提交事务
mapper.updateUser(new User(1, "pan", "12345"));
sqlSession.commit();

sqlSession.close();
}

3.5、insert

1、编写接口

//添加用户
int insertUser(User user);

2、编写接口对象的mapper中的sql语句

<insert id="insertUser" parameterType="pers.mobian.pojo.User" >
insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
</insert>

3、测试

@Test
public void insertUser() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
//执行对应的sql语句,且需要提交事务
mapper.insertUser(new User(5,"王麻子","0011"));
sqlSession.commit();

sqlSession.close();
}

注意:

其中的增删改需要提交事务

3.6、补充一个万能的Map方式

1、编写接口

//增加用户
int insertUser2(Map<String, Object> map);

2、编写接口对象的额mapper中的sql语句

<insert id="insertUser2" parameterType="map" >
<!-- 使用map的方式,可以将参数的类型进行变化-->
insert into mybatis.user (id,name,pwd) values (#{ID1},#{NAME},#{PWD});
</insert>

3、测试

@Test
public void insertUser2() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);

Map<String, Object> map = new HashMap<String, Object>();
map.put("ID1",231);
map.put("NAME",11);
map.put("PWD",11);
mapper.insertUser2(map);

sqlSession.commit();
sqlSession.close();
}

总结:

Map传递参数,直接在sql中取出key即可。—>parameterType=“map”

对象传递参数,直接在sql中取出对象的属性即可 —>parameterType=“Object”

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

多个参数用Map,或者注解

3.7、模糊查询

1、在java代码中实现模糊查询

List<User> getUserListLike(String name);

<select id="getUserListLike" resultType="pers.mobian.pojo.User">
select * from mybatis.user where name like "%"#{value}"%"
</select>

public void getUserListLike() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
//查询用户名字中包含王的
List<User> userList = userDao.getUserListLike("%王%");
for (User user : userList) {
System.out.println(user.toString());
}
sqlSession.close();

}

2、使用sql语句实现模糊查询

List<User> getUserListLike(String name);

<select id="getUserListLike" resultType="pers.mobian.pojo.User">
select * from mybatis.user where name like "%"#{value}"%"
</select>

public void getUserListLike() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
//查询用户名字中包含一的
List<User> userList = userDao.getUserListLike("1");
for (User user : userList) {
System.out.println(user.toString());
}
sqlSession.close();

}

4、配置解析

4.1、核心配置文件(configuration)

  • mybatis-config.xml
  • MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

注意:注意配置的顺序只能以指定方式进行

MyBatis_User

4.2、环境配置(environment)

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境

所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例。

<!--使用名字为test的的环境-->
<environments default="test">
<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=UTF-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>

<environment id="test">
<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=UTF-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>

事务管理器(transactionManager)

在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):

  • JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
  • MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>

提示 如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

数据源(dataSource)

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

  • 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。

有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):

UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。

POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。

JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。

4.3、属性(properties)

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

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置,也可以通过properties元素的子元素来传递(db.properties)

编写一个配置文件

db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&;serverTimezone=UTC
username=root
password=

在核心配置文件中映入

<configuration>
<properties resource="db.properties">
<property name="username" value="root"></property>
<property name="password" value=""></property>
</properties>

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

</configuration>

总结:

  • 可以使用标签直接引入对应的properties文件
  • 可以在其中增加一些属性配置
  • 如果两个文件中包含了同一个字段,优点使用外部配置文件的

4.4、别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。

它仅用于 XML 配置,意在降低冗余的全限定类名书写

<typeAliases>
<typeAlias alias="user" type="pers.mobian.pojo.User"></typeAlias>
</typeAliases>

也可以指定一个包名,MyBatis 会在包名下面搜索需要的Java Bean,比如:

扫描实体类包,它的默认别名就是为这个类的类名,首字母小写

<typeAliases>
<package name="pers.mobian.pojo" ></package>
</typeAliases>

总结:

  • 在实体类比较少的时候,建议使用第一种方式
  • 在实体类多的时候,建议使用第二种方式
  • 第一种可以自定义别人,第二种不可以直接自定义,但是可以通过注解的方式实现
@Alias("user")
public class User {}

4.5、设置(settings)

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为

设置名

描述

有效值

默认值

cacheEnabled

全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。

true | false

true

lazyLoadingEnabled

延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 ​​fetchType​​ 属性来覆盖该项的开关状态。

true | false

false

mapUnderscoreToCamelCase

是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。

true | false

False

logImpl

指定 MyBatis 所用日志的具体实现,未指定时将自动查找。

SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING

未设置

<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
</settings>

4.6、其他配置

  • typeHandlers(类型处理器)
  • objectFactory(对象工厂
  • plugins(插件)
  • mybatis-generator-core
  • mybatis-plus
  • 通用mapper

4.7、映射器(mappers)

MapperRegistry:注册绑定我们的Mapper文件

方式一:通常使用

<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

方式二:不建议使用

<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>

方式三:

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

方式四:类似于别名的扫描机制

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>

方法三和方法四使用注意:

  • 接口和对应的mapper配置文件必须在同名下
  • 接口和对应的mapper配置文件必须在同一个包下

4.8、生命周期

MyBatis_sql_02

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

SqlSessionFactoryBuilder:

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

SqlSessionFactory:

  • 可以想象成一个数据库连接池
  • SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
  • 即其最佳的作用域是应用作用域
  • 最简单得就是使用单例模式或者静态单例模式

SqlSession:

  • 连接到连接池得一个请求
  • SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
  • 使用完毕之后,应该尽快关闭,否则资源会被占用

MyBatis_sql_03

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

5、解决属性名和字段名不一致的问题

5.1、问题描述

当数据库的种的字段名和我们的实体类的属性名不一致时。如果是查询语句,则对应的字段为null。

最基本的方式:去别名

<select id="getUserById" resultType="pers.mobian.pojo.User">
select * from mybatis.user where id=#{id}
select id,name,pwd as password from mybatis.user where id=#{id}
</select>

5.2、resultMap

结果集映射:

id name pwd
id name password
<resultMap id="byId" type="pers.mobian.pojo.User">
<!--column:数据库种的字段 property:表示实体类的属性 -->
<result column="id" property="id"></result>
<result column="name" property="name"></result>
<result column="pwd" property="password"></result>
</resultMap>

<select id="getUserById" resultMap="byId">
select * from mybatis.user where id=#{id}
</select>

要点:

  • resultMap元素是MyBatis种最重要最强大的元素
  • ResultMap的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就好了
  • 如果你对ResultMap已经足够了解,那么其实可以跟简单的去使用它
<resultMap id="byId" type="pers.mobian.pojo.User">
<result column="pwd" property="password"></result>
</resultMap>

<select id="getUserById" resultMap="byId">
select * from mybatis.user where id=#{id}
</select>

6、日志

6.1、日志工厂

如果一个数据库,出现了异常,我们需要排错。于是就引入了日志

日志分类:

  • SLF4J
  • LOG4J(掌握)
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING(掌握)
  • NO_LOGGING

STDOUT_LOGGING:标准的日志输出

<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

输出日志详情

MyBatis_List_04

6.2、Log4j

  • Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件。
  • 我们也可以控制每一条日志的输出格式
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程
  • 可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码

1、导入maven依赖:

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

2、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/mobian.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}][%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

3、配置log4j的日志实现

<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>

简单使用:

  1. 需要导入对应的包
import org.apache.log4j.Logger;
  1. 日志对象,为当前的class类
static Logger logger = Logger.getLogger(UserMapperTest.class);
  1. 测试
@Test
public void log4jTest() {
logger.info("info:进入了log4jTest");
logger.debug("debug:进入了log4j");
logger.error("error:进入了log4j");

}

7、分页

目的:

减少数据的处理量

7.1、使用Limit分页:(SQL层面)

select * from user limit startIndex,pageSize
select * from user limit 0,2;

使用MyBatis 实现分页查询,核心SQL:(使用万能的map形式)

  1. 接口
List<User> getUserLimit(Map<String,Integer> map);
  1. Mapper.xml
<resultMap id="byId" type="pers.mobian.pojo.User">
<result column="pwd" property="password"></result>
</resultMap>

<select id="getUserLimit" resultMap="byId" parameterType="map">
select * from mybatis.user limit #{startIndex},#{pageSize};
</select>
  1. 测试
@Test
public void getUsrLimit() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("startIndex", 1);
map.put("pageSize", 2);

List<User> userLimit = userMapper.getUserLimit(map);
for (User user : userLimit) {
System.out.println(user);
}
}

7.2、使用RowBounds分页:(Java代码层面)

  1. 接口
List<User> getUserRowBounds();
  1. Mapper.xml
<resultMap id="byId" type="pers.mobian.pojo.User">
<result column="pwd" property="password"></result>
</resultMap>

<select id="getUserRowBounds" resultMap="byId" >
select * from mybatis.user;
</select>
  1. 测试
@Test
public void getUserRowBounds() {
SqlSession sqlSession = MybatisUtil.getSqlSession();

//实例化一个RowBounds对象,其底层依然是limit分页
RowBounds rowBounds = new RowBounds(1,3);
List<User> userList= sqlSession.selectList("pers.mobian.dao.UserMapper.getUserRowBounds", 0, rowBounds);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}

7.3、分页插件

Mybatis pageHelper

8、使用注解开发

8.1、面向接口编程

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

关于接口的理解

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

三个面向区别

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

8.2、使用注解开发

MyBatis 最初配置信息是基于 XML ,映射语句(SQL)也是定义在 XML 中的。而到MyBatis 3提供了新的基于注解的配置。不幸的是,Java 注解的的表达力和灵活性十分有限。最强大的 MyBatis 映射并不能用注解来构建

  1. 注解在接口类上实现
public interface UserMapper {

@Select("select * from user")
List<User> getUser();
}
  1. 需要在核心配置文件上绑定对应的接口:(将原来的资源文件,编程class,这也是导入资源文件的四种方法之一)
<mappers>
<mapper class="pers.mobian.dao.UserMapper"></mapper>
</mappers>
  1. 测试
@Test
public void getUser() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

List<User> userList = mapper.getUser();
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}

注解的本质:使用了反射机制

注解的底层:动态代理

补充:MyBatis 详细的执行流程:

MyBatis_List_05

8.3、CRUD

我们可以在MybatisUtil工具类创建的时候设置自动提交事务

public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}

使用注解进行开发:

注解直接写在mapper接口类种

package pers.mobian.dao;

import org.apache.ibatis.annotations.*;
import pers.mobian.pojo.User;

import java.util.List;

public interface UserMapper {

@Select("select * from user")
List<User> getUser();

@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 insertUser(User user);

@Update("update user set name=#{name},id=#{id},pwd=#{pwd} where id=#{id}")
int updateUser(User user);


@Delete("delete from user where id =#{id}")
int deleteUser(@Param("id") int id);
}

不要忘记在mybatis-config.xml配置文件中绑定我们的接口

关于@Param()注解

  • 基本类型的参数或者String类型,需要加上
  • 引用数据类型不需要添加
  • 如果只有一个基本来行,可以忽略,但是建议加上
  • 在SQL中引用的就是我们@Param()中设定的属性名

补充:#{}与${}的区别

前者可以防止SQL注入,建议使用前者

9、Lombok

使用步骤:

  1. 在IDEA中安装Lombok的插件

MyBatis_List_06

  1. 导入maven依赖(或者jar包)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
  1. 所有用法
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger
@Data
@Builder
@Singular
@Delegate
@Value
@Accessors
@Wither
@SneakyThrows
from Intellij 14.1 @val
from Intellij 15.0.2 @var
from Intellij 14.1 @var
from Intellij 2016.2 @UtilityClass
Lombok config system
Code inspections
Refactoring actions (lombok and delombok)
  1. 经常使用
@Data:无参构造、set、get、toString、hashcode、equals
@AllArgsConstructor:全参构造
@NoArgsConstructor:无参构造
@EqualsAndHashCode:hashcode、equals

10、多对一处理

10.1、搭建测试环境

  1. 在数据库中建表
  2. 新建实体类Teacher、Student
  3. 在对应的路径(dao)下创建Mapper接口
  4. 在对应的路径下(接口同路径)下新建对应的Mapper.xml文件
  5. 在核心配置文件中绑定Mapper接口或者文件
  6. 测试类,测试是否能够查询成功

SQL代码:

`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT into teacher(id,`name`) VALUES (1,"mobian");

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);
INSERT into `student` (`id`,`name`,`tid`) VALUES (6,"小钱",1);

10.2、按照查询嵌套处理

<!--1、查询最初的自己的表格,由于含有对象属性,所以使用resultMap-->
<select id="getStudent" resultMap="studentTeacher">
select * from mybatis.student;
</select>
<!--2、对于跳转过来的查询,需要一一对照属性列表-->
<resultMap id="studentTeacher" type="pers.mobian.pojo.Student">
<!--2.1、前两个是自己本身了包含的属性-->
<result property="id" column="id"></result>
<result property="name" column="name"></result>

<!--2.2、这个属性是对象属性,于是带着自己包含的tid属性,跳转到另一个查询-->
<association property="teacher" column="tid" javaType="pers.mobian.pojo.Teacher"
select="getTeacher"></association>
</resultMap>

<!--3、跳转到这里,将携带的数据与自己的属性进行对比,如果相同就返回-->
<select id="getTeacher" resultType="pers.mobian.pojo.Teacher">
select * from mybatis.teacher where id=#{id}
</select>

10.3、按照结果嵌套处理

<!--1、由于查询的属性中含有对象属性,所以使用resultMap标签,进行映射-->
<select id="getStudent2" resultMap="studentTeacher2">
<!--2、执行标准的SQL查询语句 -->
select s.id sid,s.name sname,t.name tname from mybatis.student s,mybatis.teacher t where s.id=t.id;
</select>

<!--3、对于跳转过来的映射查询,需要一一对照属性列表-->
<resultMap id="studentTeacher2" type="pers.mobian.pojo.Student">
<!--3.1、对于包含的基本属性进行映射-->
<result column="sid" property="id"></result>
<result column="sname" property="name"></result>
<!--3.2、对于包含的对象属性使用此方式映射,javaType是为指定对象中需要查询的属性-->
<association property="teacher" javaType="pers.mobian.pojo.Teacher">
<!--4、按照对应的关系,再次进行映射即可-->
<result property="name" column="tname"></result>
</association>
</resultMap>

11一对多处理

11.1、搭建环境

11.2、按照查询嵌套处理

<select id="getTeacher" resultMap="TeacherStudent">
<!--使用恰当的SQL语句-->
select t.id tid,t.name tname,s.id sid,s.name sname
from student s,teacher t
where s.tid = t.id and t.id =#{tid}
</select>

<resultMap id="TeacherStudent" type="pers.mobian.pojo.Teacher">
<result column="tid" property="id"></result>
<result column="tname" property="name"></result>
<!--复杂的属性,我们需要单独处理,对象:association 集合:collection
javaType="" 指定属性的类型
集合中的泛型信息,我们使用ofType获取
此处,将属性中的对象中的属性进行一一映射
-->
<collection property="students" ofType="pers.mobian.pojo.Student">
<result property="id" column="sid"></result>
<result property="name" column="sname"></result>
</collection>
</resultMap>

11.3、按照结果嵌套查询

<select id="getTeacher2" resultMap="TeacherStudent2">
select * from mybatis.teacher where id = #{tid}
</select>

<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId"
column="id"></collection>
</resultMap>

<select id="getStudentByTeacherId" resultType="Student">
select * from mybatis.student where tid = #{tid}
</select>

11.4、总结

  1. 关联 associate(多对一)
  2. 集合 collection(一对多)
  3. javaType 和 ofType
  • javaType是用来指定实体类中属性的类型
  • ofType用来指定映射到List或者集合中的pojo类型,泛型中的约束类型

注意点:

  • 保证SQL的可读性
  • 注意一对多和多对一中的属性和字段的问题
  • 方便排错,可以使用Log4j日志

面试高频问点:

  • Mysql引擎
  • InnoDB底层原理
  • 索引
  • 索引优化、

12、动态SQL

动态SQL就是指根据不同的条件生成不同的SQL语句,在SQL层面,执行逻辑代码

动态SQL元素和JSTL或基于类似XML的文本处理器相似。Mybatis之前的版本中,有很多元素需要花时间了解。Mybatis 3大大精简了元素种类,现在只需要学习原来一半的元素即可。Mybatis采用功能更加强打的基于OGNL的表达式来淘汰其他大部分元素

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

添加一个打印动态ID的工具类

package pers.mobian.utils;
import java.util.UUID;

public class IDutils {
public static String getId(){
return UUID.randomUUID().toString().replaceAll("-","");
}
}

搭建环境

12.1、IF

  1. 实体类
private String id;
private String title;
private String author;
private int views;
private Date createTime;
  1. Mapper接口
List<Blog> seletBlogIF(Map map);
  1. Mapper接口的对应实现类
<insert id="insertBlog" parameterType="blog">
insert into mybatis.blog(id, title, author, create_time, views)
values (#{id},#{title},#{author},#{createTime},#{views})
</insert>

<select id="seletBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog where 1=1
<if test="title != null">
and title=#{title}
</if>
<if test="views != null">
and views =#{views}
</if>
</select>
  1. 对应的测试类
@Test
public void selectBlogIF(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
map.put("title","Spring");
mapper.seletBlogIF(map);

sqlSession.close();
}

12.2、trim(where, sert)

<select id="seletBlogIF" parameterType="map" resultType="blog">

select * from mybatis.blog
<!--where标签的作用为自动附带一个可变的where-->
<where>
<if test="title != null">
title=#{title}
</if>
<if test="views != null">
and views =#{views}
</if>
</where>

</select>
<update id="updateBlog" parameterType="map">

update mybatis.blog
<!--set关键字,可以将不必要的逗号-->
<set>
<if test="title != null">
title =#{title},
</if>
<if test="views != null">
views = #{views}
</if>
</set>
where id=#{id}

</update>

12.3、choose(when, otherwise)

<select id="seletBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog

<where>
<choose>

<when test="title != null">
title = #{title}
</when>
<when test="views != null">
and wiews= #{views}
</when>
<otherwise>
and views = #{views}
</otherwise>

</choose>
</where>

</select>

12.4、SQL片段

将一部分SQL代码抽取出来,实现代码的复用

<sql id="if-title-views">
<if test="title != null">
and title=#{title}
</if>
<if test="views != null">
and views =#{views}
</if>
</sql>

<select id="seletBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog where
<where>
<include refid="if-title-views"></include>
</where>
</select>

注意事项:

  • 最好基于单表来定义SQL片段
  • 不要将where标签写进SQL片段

12.5、ForEach

  1. Mapper接口
List<Blog> seletBlogFoeEach(Map map);
  1. Mapper.xml
<!--
使用foeeach标签,达到下面SQL的效果
select * from mybits.blog where 1=1 and (id =1 or id =2 or id = 3)
-->

<select id="seletBlogFoeEach" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<!-- open为前缀,close为后缀,遍历views集合中的数据(数据来自测试类中),每一项赋值给view,再将view进行传值-->
<foreach collection="views" item="view" open="and (" close=")" separator="or">
views = #{view}
</foreach>
</where>
</select>
  1. 测试类
@Test
public void seletBlogFoeEach() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();

ArrayList<Integer> views = new ArrayList<Integer>();
//给.xml文件中的循环的views进行设置相关的内容
views.add(1);

map.put("views", views);
List<Blog> blogs = mapper.seletBlogFoeEach(map);

for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
  1. 效果

MyBatis_List_07

12.6、大量的练习

建议:先写出正常的SQL再改写成动态SQL语句

13、缓存

每次连接数据库查询,耗费资源。我们可以将查询的数据暂存在一个地方,当再次查询到相同的数据的时候,就可以直接使用不用再去数据库中查找

13.1、简介

  1. 什么是缓存 [ Cache ]?
  • 存在内存中的临时数据。
  • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
  1. 为什么使用缓存?
  • 减少和数据库的交互次数,减少系统开销,提高系统效率。
  1. 什么样的数据能使用缓存?
  • 经常查询并且不经常改变的数据。

13.2、MyBatis 缓存

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

13.3、一级缓存

一级缓存也叫本地缓存:

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

测试步骤:

  1. 开启日志
  2. 测试一个在Session中查询两次相同的记录
@Test
public void selectUserById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.selectUserById(2);

System.out.println(user.toString());
User user2 = mapper.selectUserById(2);
System.out.println("===");
System.out.println(user2.toString());
sqlSession.close();
}
  1. 查看对应的日志

MyBatis_sql_08

缓存失效的情况:

  1. 使用增删改操作以后,会改变原来的数据,所以会刷新缓存

MyBatis_sql_09

  1. 查询不同的数据
  2. 查询不同的Mapper.xml文件
  3. 在一个mapper的操作过程中(一次会话过程中),手动清理缓存
sqlSession.clearCache();

总结:一级缓存是默认开启的,只在一次SqlSession中有效,也就是从连接JDBC连接开启,到将连接返回到连接池中。

13.4、二级缓存

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

步骤:

  1. 开启全局缓存
<!--开启全局缓存,默认是开启的-->
<setting name="cacheEnabled" value="true"/>
  1. 在要使用的二级缓存中开启
<!--在当前的Mapper.xml中使用并设置二级缓存
eviction:使用FIFO的清除缓存策略,有四种:LRU(默认)、FIFO、SOFT、WEAK
flushInterval:每隔60s刷新一次
size:最多可以存储结果对象或列表的 512 个引用
readOnly:回的对象被认为是只读的
-->
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>


<!--默认使用-->
<cache/>
  1. 测试
@Test
public void selectUserById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.selectUserById(2);
sqlSession.close();


SqlSession sqlSession2 = MybatisUtil.getSqlSession();
UserMapper mapper1 = sqlSession2.getMapper(UserMapper.class);
mapper1.selectUserById(2);
sqlSession2.close();
}

注意:

  1. 在使用的过程中需要将实体类进行系列化,即实现Serializable接口
  2. 所有的数据都会先放在一级缓存中,只有当会话提交以后,或者关闭的时候,才会提交到二级缓存中
  3. 开启二级缓存后,只有是获取的同一个Mapper.xml就有效

13.5、缓存原理

缓存的执行流程:

MyBatis_sql_10

13.6、自定义缓存

1、使用Ehcache

  • Ehcache是一种广泛使用的java分布式缓存,用于通用缓存;
  • 要在应用程序中使用Ehcache,需要引入依赖的jar包
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
  • 在mapper.xml中使用对应的缓存即可
<mapper namespace = “UserMapper” > 
<cache type = “org.mybatis.caches.ehcache.EhcacheCache” />
</mapper>
  • 编写ehcache.xml文件,如果在​​加载时​​未找到/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:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
user.home – 用户主目录
user.dir – 用户当前工作目录
java.io.tmpdir – 默认临时文件路径
-->
<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"/>
<!--
defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
-->
<!--
name:缓存名称。
maxElementsInMemory:缓存最大数目
maxElementsOnDisk:硬盘最大缓存个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
overflowToDisk:是否保存到磁盘,当系统宕机时
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
FIFO,first in first out,这个是大家最熟的,先进先出。
LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
-->

</ehcache>

2、自定义缓存样式

实现Cache接口,重写其中的方法即可

package pers.mobian.pojo;

import org.apache.ibatis.cache.Cache;

import java.util.concurrent.locks.ReadWriteLock;

public class MyCache implements Cache
{
public String getId() {
return null;
}

public void putObject(Object key, Object value) {

}

public Object getObject(Object key) {
return null;
}

public Object removeObject(Object key) {
return null;
}

public void clear() {

}

public int getSize() {
return 0;
}

public ReadWriteLock getReadWriteLock() {
return null;
}
}


标签:缓存,name,mybatis,sqlSession,user,MyBatis,id
From: https://blog.51cto.com/u_15942107/6019964

相关文章

  • Mybatis-Plus批量插入应该怎么用
    没有绝路,人也不会死在绝路上,大众只会迷失于路口文章目录​​1.准备测试环境​​​​2.saveBatch​​​​2.1分析​​​​3.insert循环插入​​​​4.自定义sql插入​​......
  • MyBatis-Plus联表查询(Mybatis-Plus-Join)
    ​​mybatis-plus​​​作为​​mybatis​​​的增强工具,简化了开发中的数据库操作。一旦遇到leftjoin或rightjoin的左右连接,还是得老老实实的打开xml文件,手写上一大段的s......
  • 分页依赖里面底层有mybatis-start 这个依赖,版本和这个项目的common的mybatis-start
    我重新提交了解决了 是我弄了分页依赖进去然后分页依赖里面底层有mybatis-start这个依赖,版本和这个项目的common的mybatis-start 版本依赖不一致导致的,我用mybatis......
  • (狂神)MyBatis-Plus
    Ref:https://www.kuangstudy.com/1、MyBatisPlus概述需要的基础:把我的MyBatis、Spring、SpringMVC就可以学习这个了!为什么要学习它呢?MyBatisPlus可以节省我们大量工......
  • 使用MyBatis-Plus报错:Invalid bound statement (not found):无法使用selectById云云
    详见MP的gitee源码Issue:https://gitee.com/baomidou/mybatis-plus/issues/I6AZIOMP版本3.5.2最近遇到了Invalidboundstatement(notfound)这个报错,网上都是说xml和mapp......
  • MyBatis-XML和注解
    参考:https://www.cnblogs.com/lyc-smile/p/9055856.htmlhttps://ld246.com/article/1488810828678https://blog.csdn.net/qq_41617744/article/details/80224721  ......
  • MyBatis
    MyBatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层Dao框架。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以对配置和原生Ma......
  • 小工具:解决mybatis的保存、更新大量字段问题,tk.mybatis。
    小工具:解决mybatis的保存、更新大量字段问题,tk.mybatis。今天咕咕在CRUD搬砖的时候,发现,按照传统的写sql的方式,不管是注解开发,还是xml,是不是对于insert和uodate操作,如果有大......
  • mybatis面试资料
    1.#{}和${}的区别#{}数据类型检查:若检测到字符串类型,就加上引号;若检测到数值类型,就不加引号。安全检查:若变量的值带有引号,会对引号进行转义处理,这样可以防止sql注入......
  • mybatis
    全局配置文件*官网全局配置文件解析<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTDConfig3.0//EN"......