一、动态SQL语句
准备工作:
public class User {
private int id;
private String lastName;
private int sex;
1、if 语句
说明: if语句,可以动态的根据你的值来决定,是否需要动态的添加查询条件。
方法代码:
public interface UserMapper {
/**
* 根据用户的lastName属性和sex属性查询用户信息
* 前提条件是lastName属性和sex属性值都合法。
* 如果lastName属性和sex属性哪个不合法,就不要加入查询条件
*/
public List queryUserByNameAndSex(User user);
}
配置信息:
select
id,last_name lastName,sex
from
t_user
where
last_name like concat('%',#{lastName},'%')
and sex = #{sex}
测试代码:
@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();
}
}
2、where 语句
说明: where语句,可以帮我们在多个动态语句中,有效的去掉前面的多余的and 或 or 之类的多余关键字
select
id,last_name lastName,sex
from
t_user
last_name like concat('%',#{lastName},'%')
and sex = #{sex}
3、trim语句
说明: trim 可以动态在包含的语句前面和后面添加内容。也可以去掉前面或者后面给定的内容
prefix 前面添加内容
suffix 后面添加内容
suffixOverrides 去掉的后面内容
prefixOverrides 去掉的前面内容
方法代码:
public List queryUserByNameAndSexTrim(User user);
配置信息:
select
id,last_name lastName,sex
from
t_user
last_name like concat('%',#{lastName},'%') and
sex = #{sex}
测试代码:
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();
}
}
4、choose( when , otherwise )语句
说明:choose when otherwise 可以执行多路选择判断,但是只会有一个分支会被执行。
类似switch case 语句
方法:
/**
* 根据user对象的属性进行查询
* 1、如果lastName值有效(非空),则做模糊查询
* 2、sex属性如果有效,就做性别查询
* 3、使用默认条件查询
*/
public List queryUsersByNameOrSexChoose(User user);
配置信息:
select
id,last_name lastName,sex
from
t_user
last_name like concat('%',#{lastName},'%')
sex = #{sex}
1 = 1
测试代码:
@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();
}
}
5、set语句
删除条件后的逗号
方法:
/**
* 更新user
*/
public int updateUser(User user);
配置信息:
update
t_user
last_name = #{lastName} ,
sex = #{sex}
where
id = #{id}
测试代码:
@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();
}
}
6、foreach语句
方法:
/**
* select * from t_user where id in(1,2,3)
*/
public List queryUsersByIds(List ids);
配置信息:
select
id,last_name lastName,sex
from
t_user
where
id in
#{i}
测试代码:
@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();
}
}
二、mybatis缓存
缓存:所谓是指把一些经常访问的数据保存到一个调整的缓冲区中。保存在高速缓冲区中的数据叫缓存。
一级缓存:指的是缓存在SqlSession中的数据(默认开启,并且不能关闭)
二级缓存:指的是缓存在SqlSessionFactory中的数据(需要手动开启和配置)
1、mybatis的一级缓存的示例
一级缓存测试代码:
@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();
}
}
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();
}
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();
}
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();
}
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();
}
2、mybatis的二级缓存
二级缓存的图解示意
二级缓存的使用:
myBatis的二级缓存默认是不开启的。
1、我们需要在mybatis的核心配置文件中配置setting选项
2、在Mapper的配置文件中加入cache标签。
3、需要被二级缓存的对象必须要实现java的序列化接口。
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();
}
2.2、useCache="false"的演示和说明
select id,last_name lastName,sex from t_user where id = #{id}
2.3、flushCache="false"的演示和说明
flushCache刷新或清空缓存
update t_user set last_name = #{lastName},sex = #{sex} where id = #{id}
2.4、标签的介绍和说明
默认的标签的作用:
1、映射语句文件中的所有 select 语句将会被缓存。
2、射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
3、缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
4、根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
5、缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
6、缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
cache标签示例解析:
eviction属性表示缓存策略。
LRU – 最近最少使用的:移除最长时间不被使用的对象(这是默认策略)。
FIFO– 先进先出:按对象进入缓存的顺序来移除它们。
SOFT– 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK– 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval 属性表示间隔多长时间刷新一下缓冲区,清理一下溢出的数据。以毫秒为单位。
size 属性表示缓存中可以保存多少个对象。默认是1024。
readOnly 属性表示是否只读。如果设置为true。表示缓存中只有一个对象。如果设置为false(默认为false)每次取出来都会反序列化拷贝一份。
type 属性表示自定义二级缓存对象。
自定义二级缓存:
编写一个类去实现Cache接口
到mapper配置文件的cache标签中配置type属性
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();
}
}
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接口对应的配置文件
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;
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">
运行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);
}
}
文件路径: