mybatis缓存与mysql缓存_MyBatis(三)动态SQL与缓存

一、动态SQL语句

准备工作:

public class User {

private int id;

private String lastName;

private int sex;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

1、if 语句

说明: if语句,可以动态的根据你的值来决定,是否需要动态的添加查询条件。

方法代码:

public interface UserMapper {

/**

* 根据用户的lastName属性和sex属性查询用户信息

* 前提条件是lastName属性和sex属性值都合法。

* 如果lastName属性和sex属性哪个不合法,就不要加入查询条件

*/

public List queryUserByNameAndSex(User user);

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

配置信息:

select

id,last_name lastName,sex

from

t_user

where

last_name like concat('%',#{lastName},'%')

and sex = #{sex}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

测试代码:

@Test

public void testQueryUserByNameAndSex() {

SqlSession session = sqlSessionFactory.openSession();

try {

UserMapper mapper = session.getMapper(UserMapper.class);

mapper.queryUserByNameAndSex(new User(null, "bb", 10)).forEach(System.out::println);

} catch (Exception e) {

e.printStackTrace();

} finally {

session.close();

}

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2、where 语句

说明: where语句,可以帮我们在多个动态语句中,有效的去掉前面的多余的and  或 or 之类的多余关键字

select

id,last_name lastName,sex

from

t_user

last_name like concat('%',#{lastName},'%')

and sex = #{sex}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3、trim语句

说明: trim 可以动态在包含的语句前面和后面添加内容。也可以去掉前面或者后面给定的内容

prefix 前面添加内容

suffix 后面添加内容

suffixOverrides 去掉的后面内容

prefixOverrides 去掉的前面内容

方法代码:

public List queryUserByNameAndSexTrim(User user);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

配置信息:

select

id,last_name lastName,sex

from

t_user

last_name like concat('%',#{lastName},'%') and

sex = #{sex}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

测试代码:

public void testQueryUserByNameAndSexTrim() {

SqlSession session = sqlSessionFactory.openSession();

try {

UserMapper mapper = session.getMapper(UserMapper.class);

mapper.queryUserByNameAndSexTrim(new User(null, "bb", 10)).forEach(System.out::println);

} catch (Exception e) {

e.printStackTrace();

} finally {

session.close();

}

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

4、choose( when , otherwise )语句

说明:choose when otherwise 可以执行多路选择判断,但是只会有一个分支会被执行。

类似switch case 语句

方法:

/**

* 根据user对象的属性进行查询

* 1、如果lastName值有效(非空),则做模糊查询

* 2、sex属性如果有效,就做性别查询

* 3、使用默认条件查询

*/

public List queryUsersByNameOrSexChoose(User user);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

配置信息:

select

id,last_name lastName,sex

from

t_user

last_name like concat('%',#{lastName},'%')

sex = #{sex}

1 = 1

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

测试代码:

@Test

public void testQueryUsersByNameOrSexChoose() {

SqlSession session = sqlSessionFactory.openSession();

try {

UserMapper mapper = session.getMapper(UserMapper.class);

mapper.queryUsersByNameOrSexChoose(new User(null, null, 10)).forEach(System.out::println);

} catch (Exception e) {

e.printStackTrace();

} finally {

session.close();

}

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

5、set语句

删除条件后的逗号

方法:

/**

* 更新user

*/

public int updateUser(User user);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

配置信息:

update

t_user

last_name = #{lastName} ,

sex = #{sex}

where

id = #{id}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

测试代码:

@Test

public void testUpdateUser() {

SqlSession session = sqlSessionFactory.openSession();

try {

UserMapper mapper = session.getMapper(UserMapper.class);

mapper.updateUser(new User(4, "ccc", 10));

session.commit();

} catch (Exception e) {

e.printStackTrace();

} finally {

session.close();

}

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

6、foreach语句

方法:

/**

* select * from t_user where id in(1,2,3)

*/

public List queryUsersByIds(List ids);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

配置信息:

select

id,last_name lastName,sex

from

t_user

where

id in

#{i}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

测试代码:

@Test

public void testQueryUsersByIds() throws Exception {

SqlSession session = sqlSessionFactory.openSession();

try {

UserMapper mapper = session.getMapper(UserMapper.class);

List ids = new ArrayList();

ids.add(1);

ids.add(2);

ids.add(3);

ids.add(4);

mapper.queryUsersByIds(ids).forEach(System.out::println);

} catch (Exception e) {

e.printStackTrace();

} finally {

session.close();

}

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

二、mybatis缓存

缓存:所谓是指把一些经常访问的数据保存到一个调整的缓冲区中。保存在高速缓冲区中的数据叫缓存。

一级缓存:指的是缓存在SqlSession中的数据(默认开启,并且不能关闭)

二级缓存:指的是缓存在SqlSessionFactory中的数据(需要手动开启和配置)

1、mybatis的一级缓存的示例924c508d3b9b9dfc11ecff525943cb21.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

一级缓存测试代码:

@Test

public void testFirstLevelCache() throws Exception {

SqlSession session = sqlSessionFactory.openSession();

try {

UserMapper mapper = session.getMapper(UserMapper.class);

System.out.println( mapper.queryUserById(1) );

System.out.println( mapper.queryUserById(1) );

} catch (Exception e) {

e.printStackTrace();

} finally {

session.close();

}

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

1.2、一级缓存的管理

一级缓存失效的四种情况:

1.不在同一个SqlSession对象中

@Test

public void testFirstLevelCacheFail1() throws Exception {

queryOne();

queryOne();

}

private void queryOne(){

SqlSession session = sqlSessionFactory.openSession();

UserMapper mapper = session.getMapper(UserMapper.class);

System.out.println(mapper.queryUserById(1));

session.close();

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.执行语句的参数不同。缓存中也不存在数据。

@Test

public void testFirstLevelCacheFail2() throws Exception {

SqlSession session = sqlSessionFactory.openSession();

UserMapper mapper = session.getMapper(UserMapper.class);

System.out.println(mapper.queryUserById(1));

System.out.println(mapper.queryUserById(2));

session.close();

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3.执行增,删,改,语句,会清空掉缓存

@Test

public void testFirstLevelCacheFail3() throws Exception {

SqlSession session = sqlSessionFactory.openSession();

UserMapper mapper = session.getMapper(UserMapper.class);

System.out.println(mapper.queryUserById(1));

mapper.updateUser(new User(1, "cadsrq", 1));//执行增,删,改,语句,会清空掉缓存

System.out.println(mapper.queryUserById(1));

session.close();

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

4.手动清空缓存数据

@Test

public void testFirstLevelCacheFail4() throws Exception {

SqlSession session = sqlSessionFactory.openSession();

UserMapper mapper = session.getMapper(UserMapper.class);

System.out.println(mapper.queryUserById(1));

session.clearCache();//清空缓存

System.out.println(mapper.queryUserById(1));

session.close();

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2、mybatis的二级缓存

二级缓存的图解示意

b850512d633dfb0182e4c7bbaea4fc0c.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

二级缓存的使用:

myBatis的二级缓存默认是不开启的。

1、我们需要在mybatis的核心配置文件中配置setting选项

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2、在Mapper的配置文件中加入cache标签。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3、需要被二级缓存的对象必须要实现java的序列化接口。

dc5527d74830c746b74556972dc1653c.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.1、二级缓存的演示

private void queryOne(){

SqlSession session = sqlSessionFactory.openSession();

UserMapper mapper = session.getMapper(UserMapper.class);

System.out.println(mapper.queryUserById(1));

session.close();

}

@Test

public void testSecondLevelCache() throws Exception {

queryOne();

queryOne();

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.2、useCache="false"的演示和说明

select id,last_name lastName,sex from t_user where id = #{id}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.3、flushCache="false"的演示和说明

flushCache刷新或清空缓存

update t_user set last_name = #{lastName},sex = #{sex} where id = #{id}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.4、标签的介绍和说明

默认的标签的作用:

1、映射语句文件中的所有 select 语句将会被缓存。

2、射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。

3、缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。

4、根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。

5、缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。

6、缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

cache标签示例解析:

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

eviction属性表示缓存策略。

LRU – 最近最少使用的:移除最长时间不被使用的对象(这是默认策略)。

FIFO– 先进先出:按对象进入缓存的顺序来移除它们。

SOFT– 软引用:移除基于垃圾回收器状态和软引用规则的对象。

WEAK– 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

flushInterval       属性表示间隔多长时间刷新一下缓冲区,清理一下溢出的数据。以毫秒为单位。

size                    属性表示缓存中可以保存多少个对象。默认是1024。

readOnly            属性表示是否只读。如果设置为true。表示缓存中只有一个对象。如果设置为false(默认为false)每次取出来都会反序列化拷贝一份。

type                    属性表示自定义二级缓存对象。

自定义二级缓存:

编写一个类去实现Cache接口

到mapper配置文件的cache标签中配置type属性

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

public class MyCache implements Cache {

private String id;

private Map cache = new HashMap();

public MyCache(String id) {

this.id = id;

}

@Override

public String getId() {

return id;

}

@Override

public int getSize() {

return cache.size();

}

@Override

public void putObject(Object key, Object value) {

System.out.println("保存缓存");

cache.put(key, value);

}

@Override

public Object getObject(Object key) {

System.out.println("获取缓存");

return cache.get(key);

}

@Override

public Object removeObject(Object key) {

return cache.remove(key);

}

@Override

public void clear() {

cache.clear();

}

@Override

public ReadWriteLock getReadWriteLock() {

return null;

}

@Override

public boolean equals(Object o) {

if (getId() == null) {

throw new CacheException("Cache instances require an ID.");

}

if (this == o) {

return true;

}

if (!(o instanceof Cache)) {

return false;

}

Cache otherCache = (Cache) o;

return getId().equals(otherCache.getId());

}

@Override

public int hashCode() {

if (getId() == null) {

throw new CacheException("Cache instances require an ID.");

}

return getId().hashCode();

}

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3、缓存的使用顺序说明

当我们执行一个查询语句的时候。mybatis会先去二级缓存中查询数据。如果二级缓存中没有。就到一级缓存中查找。

如果二级缓存和一级缓存都没有。就发sql语句到数据库中去查询。

查询出来之后马上把数据保存到一级缓存中。

当SqlSession关闭的时候,会把一级缓存中的数据保存到二级缓存中。

org.apache.ibatis.cache.impl.PerpetualCache一级缓存实现类

三、mybatis逆向工程

MyBatis逆向工程,简称MBG。是一个专门为MyBatis框架使用者定制的代码生成器。可以快速的根据数据库表生成对应的映射文件,接口,以及Bean类对象。

在Mybatis中,有一个可以自动对单表生成的增,删,改,查代码的插件。

叫 mybatis-generator-core-1.3.2。

它可以帮我们对比数据库表之后,生成大量的这个基础代码。

这些基础代码有:

数据库表对应的javaBean对象

这些javaBean对象对应的Mapper接口

这些Mapper接口对应的配置文件

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

1、准备数据库表

create database mbg;

use mbg;

create table t_user(

`id` int primary key auto_increment,

`username` varchar(30) not null unique,

`password` varchar(40) not null,

`email` varchar(50)

);

insert into t_user(`username`,`password`,`email`) values('admin','admin','admin@atguigu.com');

insert into t_user(`username`,`password`,`email`) values('wzg168','123456','admin@atguigu.com');

insert into t_user(`username`,`password`,`email`) values('admin168','123456','admin@atguigu.com');

insert into t_user(`username`,`password`,`email`) values('lisi','123456','admin@atguigu.com');

insert into t_user(`username`,`password`,`email`) values('wangwu','123456','admin@atguigu.com');

create table t_book(

`id` int primary key auto_increment,

`name` varchar(50),

`author` varchar(50),

`price`decimal(11,2),

`sales`int,

`stock` int

);

## 插入初始化测试数据

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` )

values(null , 'java从入门到放弃' , '国哥' , 80 , 9999 , 9);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` )

values(null , '数据结构与算法' , '严敏君' , 78.5 , 6 , 13);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` )

values(null , '怎样拐跑别人的媳妇' , '龙伍' , 68, 99999 , 52);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` )

values(null , '木虚肉盖饭' , '小胖' , 16, 1000 , 50);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` )

values(null , 'C++编程思想' , '刚哥' , 45.5 , 14 , 95);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` )

values(null , '蛋炒饭' , '周星星' , 9.9, 12 , 53);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` )

values(null , '赌神' , '龙伍' , 66.5, 125 , 535);

select * from t_user;

select * from t_book;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

mbg配置文件内容:

/p>

PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"

"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

connectionURL="jdbc:mysql://localhost:3306/mbg"

userId="root"

password="root">

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

运行mbg的代码

import java.io.File;

import java.util.ArrayList;

import java.util.List;

import org.mybatis.generator.api.MyBatisGenerator;

import org.mybatis.generator.config.Configuration;

import org.mybatis.generator.config.xml.ConfigurationParser;

import org.mybatis.generator.internal.DefaultShellCallback;

public class Runner {

public static void main(String[] args) throws Exception {

List warnings = new ArrayList();

boolean overwrite = true;

File configFile = new File("mbg.xml");

ConfigurationParser cp = new ConfigurationParser(warnings);

Configuration config = cp.parseConfiguration(configFile);

DefaultShellCallback callback = new DefaultShellCallback(overwrite);

MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,

callback, warnings);

myBatisGenerator.generate(null);

}

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

文件路径:

6ccea8a258347fab57278f88ce9b131e.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值