准备工作
- 创建数据库
- 导入数据
- idea连接数据库:导入依赖,编写配置文件,确定数据库连接正常。
快速入门
创建一个mapper接口,这里以UserMapper为例,继承BaseMapper 中间的泛型填要操作的实体类,我们这里就填User。然后在mapper接口上标注@Mapper并在主启动类上标注@MapperScan("cn.zjq.mapper")
UserMapper
import cn.zjq.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
//这不有手就行?
}
再创建一个对应实体类,咱们就可以收工了。
import lombok.Data;
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
测试
@Autowired
UserMapper userMapper;
@Test
void contextLoads() {
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
//请把easy打在公屏上
}
开启日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
主键生成策略
在这里我们可以做一个insert测试
@Test
void contextLoads1() {
User user = new User();
user.setName("huhu");
user.setAge(2);
int insert = userMapper.insert(user);
System.out.println(insert);
System.out.println(user);
}
测试结果我们可以发现我们并没有设置id字段但是系统为我们生成了一个id字段,这里采用的时雪花算法,主键生成策略还有很多比如uuid、自增id、redis、zookeeper等。
雪花算法
@TableId(type = IdType.ID_WORKER)
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。
自增
@TableId(type = IdType.AUTO)
这个没什么可说的就是你的表也要是自增的否则会报错
更新操作
测试
@Test
void contextLoads3() {
User user = new User();
user.setId(123L);
user.setName("小王");
user.setAge(2);
userMapper.updateById(user);
}
我们可以发现sql语句时动态拼接的,他只会把你set的值拼接上去。
自动填充
创建时间、修改时间!自动化完成
阿里巴巴开发手册gmt_create、gmt_modified
方式一:数据库级别(工作中不允许修改数据库)
其实质就是在表里添加了两个字段实现自动更新
方式二:代码级别
在实体类的gmt_create和gmt_modified字段上分别加上@TableField(fill = FieldFill.INSERT) @TableField(fill = FieldFill.INSERT_UPDATE)
然后自定义一个处理器实现MetaObjectHandler接口。
实体类修改
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmtModified;
处理器
package cn.zjq.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// default MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) {
this.setFieldValByName("gmtCreate",new Date(),metaObject);
this.setFieldValByName("gmtModified",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("gmtModified",new Date(),metaObject);
}
}
乐观锁![在这里插入图片描述](https://img-blog.csdnimg.cn/86b74f774161468ca018d54df2de5822.png)
乐观锁就是在更新之前先取出版本号字段,在更新时检查版本号与之前取出的版本号是否相同,如果相同则正常更新数据,不相同则证明有其他进程在这个时候修改过了数据,则当前进程更新失败。
mybatis-plus中的乐观锁插件
修改数据库和实体类,增加一个version即版本号字段,默认值为1,实体类字段加@Version注解,然后根据官网注册一个处理器,就可以用了。
实体类修改
@Version
private Integer version;
处理器
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@MapperScan("cn.zjq.mapper")
public class HappyLockConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
这里重点解释乐观锁的使用!
乐观锁是需要先查询出来要修改的对象再用set方法重置这个对象的某些属性再update才有用!
测试!
@Test
void contextLoads4() {
User user = userMapper.selectById(1L);
user.setId(1L);
user.setName("HMF");
user.setAge(2);
userMapper.updateById(user);
}
查询
//查询id为1,2,3的记录
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
//查询name为HMF的记录
Map<String, Object> map= new HashMap<>();
map.put("name","HMF");
List<User> users1 = userMapper.selectByMap(map);
users1.forEach(System.out::println);
分页插件
插件
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
测试:Page是MP封装的一个对象,构造器中传入的两个参数是当前页和页面大小。
@Test
void contextLoads6() {
Page<User> page = new Page<>(2,5);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
System.out.println(page.getTotal());
}
查询操作
(删除同理可得)select换成delete就行了
@Test
void contextLoads6() {
Page<User> page = new Page<>(2,5);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
System.out.println(page.getTotal());
}
逻辑删除
物理删除:从数据库中删除
逻辑删除:通过一个变量让他失效 deleted=1
- 在数据库增加一个deleted字段,默认值为0
- 更新实体类字段,加上注解
@TableLogic
- 配置文件
mybatis-plus:
global-config:
db-config:
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
测试!
@Test
void contextLoads7() {
userMapper.deleteById(1483247854799917058L);
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
这里我们可以发现逻辑删除底层是一个update操作。
当我们再次查询的时候他会自动帮我们把判断deleted的条件拼接上去。
性能分析插件
挂了!
条件构造器
语句 | 含义 |
---|---|
eq | 等于 |
ne | 不等于 |
gt | 大于 |
ge | 大于等于 |
lt | 小于 |
le | 小于等于 |
between | (“字段名”,左边界,右边界) |
notBetween | 同上 |
inSql | 子查询 |
排序:
wrapper.orderByAsc("id");//desc
模糊查询
wrapper
.notLike("name","e")
.likeRight("email","t");