MybatisPlus
快速入门
使用第三方组件
- 导入对应的依赖
- 研究依赖如何配置
- 代码如何编写
- 提高扩展
配置日志
现在的sql都是不可见的,需要知道是怎么执行的,所以要有日志
#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
CRUD
插入操作
insert
//测试插入功能
@Test
public void testInsert(){
User user = new User();
user.setName("qq");
user.setAge(11);
user.setEmail("@@");
int insert = userMapper.insert(user);//帮我们自动生成id
System.out.println(insert);//受影响的行数
System.out.println(user);//id会自动回填
}
数据库插入的id的默认值为:全局的唯一id
主键生成策略
默认 ID_WORKER 全局唯一ID
主键自增
需要配置主键自增
- 在实体类字段上增加 @TableId(type=IdType.AUTO)
- 数据库字段一定要是自增
其余的源码解释
public enum IdType {
AUTO(0),//数据库id自增
NONE(1),//未设置主键
INPUT(2),//手动输入
ID_WORKER(3),//默认的全局唯一id
UUID(4),//全局唯一id uuid
ID_WORKER_STR(5);//ID_WORKER的字符串表示
}
更新操作
//测试更新
@Test
public void testUpdate(){
//通过条件自动拼接sql
User user = new User();
user.setId(4L);
user.setName("Ryota");
//注意:updateById虽然名字是id 但是参数是一个对象
int i = userMapper.updateById(user);
System.out.println(i);
System.out.println(user);
}
自动填充
创建时间,修改时间!这些操作一般都是自动化完成的,我们不希望手动更新
阿里巴巴开发手册:所有的数据库表:gmt_create,gmt_modified几乎所有的表都要配置上,而且需要自动化
方式一:数据库级别(工作中不允许使用)
- 在表中新增字段 create_time,update_time
- 再次测试插入方法,先同步实体类
private Date createTime;
private Date updateTime;
方式二:代码级别
- 删除数据库的默认值,更新操作
- 实体类的字段属性需要增加注解
//字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
- 编写处理器来处理注解即可
@Slf4j
@Component//一定不能忘记把处理器加入到IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时候的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill.......");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//更新时候的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill.........");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
- 测试插入
- 测试更新 观察时间
乐观锁
乐观锁:认为不会出现问题,无论干什么都不会去上锁,如果出现了问题,再次更新值测试
悲观锁:认为总是会出现问题,无论干什么都会上锁,再去操作
version,newversion
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
乐观锁:1. 先查询 获得版本号 version=1
--A
update user set name='qq',version = version+1
where id = 22 and version =1
--B 线程抢先完成,这个时候version=2 会导致A修改失败
update user set name='qq',version = version+1
where id = 22 and version =1
测试MybatisPlus的乐观锁插件
1.给数据库中添加version字段
2.实体类加对应的字段
@Version//乐观锁version注解
private Integer version;
3.注册组件
//扫描mapper文件夹
@MapperScan("com.ryota.mapper")
@EnableTransactionManagement//自动管理事务
@Configuration//配置类
public class MybatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
4.测试
//测试乐观锁成功
@Test
public void testOptimisticLocker(){
//1 查询用户信息
User user = userMapper.selectById(1L);
//2 修改用户信息
user.setName("Pony");
user.setEmail("pony@qq.com");
//3 执行更新操作
userMapper.updateById(user);
}
//测试乐观锁失败,多线陈下
@Test
public void testOptimisticLocker2(){
//1 线程1
User user = userMapper.selectById(1L);
user.setName("Pony");
user.setEmail("pony@qq.com");
userMapper.updateById(user);
//2 模拟另一条线程来执行插队操作
User user2 = userMapper.selectById(1L);
user2.setName("Ponyma");
user2.setEmail("ponyma@qq.com");
//自旋锁来多次尝试提交
userMapper.updateById(user2);//如果没有乐观锁就会覆盖插队线程的值
}
查询操作
//测试查询
@Test
public void testSelectById1(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
//测试批量查询
@Test
public void testSelectById(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
//按条件查询 使用map操作
@Test
public void testSelectByBatchIds(){
HashMap<String, Object> hashMap = new HashMap<>();
//自定义查询
hashMap.put("name","Pony");
hashMap.put("age",18);
List<User> users = userMapper.selectByMap(hashMap);
System.out.println(users);
}
分页查询
分页在网站中使用的十分之多
- 原始的 limit进行分页
- pageHelper第三方插件
- mybatisplus内置了分页插件
如何使用
- 配置拦截器组件
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
- 直接使用Page对象即可
//测试分页查询
@Test
public void testPage(){
//参数一:当前页
//参数二:页面的大小
//使用了分页插件之后,所有的分页操作变得简单了
Page<User> page = new Page<>(2,5);
userMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);
System.out.println(page.getTotal());
}
删除操作
//测试删除
@Test
public void deleteById(){
userMapper.deleteById(1289725499735580675L);
}
//批量删除
@Test
public void deleteBatchIds(){
userMapper.deleteBatchIds(Arrays.asList(1289725499735580674L,1289725499735580675L));
}
//通过条件删除
@Test
public void deleteByMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","娃娃");
userMapper.deleteByMap(map);
}
逻辑删除
物理删除:从数据库中直接移除
逻辑删除:在数据库中没有删除,而是通过一个变量来让他失效
遇到的例子:管理员可以查看被删除的记录 防止数据的丢失,类似回收站
测试:
- 在数据表中增加deleted字段
- 实体类中加入属性
@TableLogic//逻辑删除
private Integer deleted;
- 配置
#配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
- 测试
记录依旧在数据库,但是值却已经变化了
再次查询的时候查询不到,被逻辑删除的数据不能被查询到
条件构造器
十分重要:Wrapper
写一些复杂的sql就可以使用它来替代
@Test
void contextLoads(){
//查询name不为空的用户,并且邮箱不为空的用户,年龄大于18岁的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",22);//ge >= g:大于 e:equals
userMapper.selectList(wrapper).forEach(System.out::println);//和map对比一下
}
@Test
void test(){
//查询名字为pony的
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name","pony");
User user = userMapper.selectOne(wrapper);//查询一个数据,出现多个结果使用list或者map
System.out.println(user);
}
@Test
void test2(){
//查询年龄在22-28之间的
QueryWrapper<User> wrapper = new QueryWrapper<>();
QueryWrapper<User> age = wrapper.between("age", "22", "28");
Integer integer = userMapper.selectCount(age);//查询结果数
System.out.println(integer);
}
@Test
void test3(){
//模糊查询
QueryWrapper<User> wrapper = new QueryWrapper<>();
//左和右 t开头 t%
wrapper
.notLike("name","j")
.likeRight("email","p");
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}
ger integer = userMapper.selectCount(age);//查询结果数
System.out.println(integer);
}
@Test
void test3(){
//模糊查询
QueryWrapper wrapper = new QueryWrapper<>();
//左和右 t开头 t%
wrapper
.notLike(“name”,“j”)
.likeRight(“email”,“p”);
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}
###