前置:
MyBatis-Plus学习笔记1-入门_ML.star的博客-CSDN博客
增删改查
mp-添加操作
//添加操作
@Test
public void adduser(){
User user =new User();
user.setName("Aimi");
user.setAge(30);
user.setEmail("Aimi@qq.com");
int insert = userMapper.insert(user);
System.out.println("insert"+insert);
}
mp实现修改操作
updateById
@Test
public void updateUser(){
User user=new User();
user.setId(2L);
user.setAge(51);
int row =userMapper.updateById(user);
System.out.println(row);
}
mp简单查询
1.根据id查询
User user=userMapper.selectById(1444225850764447745L);
2.多个id批量查询
@Test
public void testSecectDemo1(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1L,2L,3L));
System.out.println(users);
}
3.根据条件去做查询
selectByMap
@Test
public void testSelectDemo2(){
HashMap<String ,Object> map =new HashMap<>();
map.put("name","小明");
map.put("age",999);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
4.分页查询
分页的插件
// 旧版
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
测试
@Test
public void testPage(){
//创建page对象
//传入两个参数,当前页 和 每页显示记录数
Page<User> page = new Page<>(1, 3);
//调用mp分页查询的方法
userMapper.selectPage(page,null );
//通过page对象获取分页数据
System.out.println(page.getCurrent());//当前页
System.out.println(page.getRecords());//每页数据list集合
System.out.println(page.getSize());//每页显示记录数
System.out.println(page.getTotal());//总记录数
System.out.println(page.getPages());//总页数
System.out.println(page.hasNext());//是否有下一页
System.out.println(page.hasPrevious());//是否有上一页
}
删除
1.物理删除
删除id为1的用户
@Test void testDeleteById(){
userMapper.deleteById(1L);
}
2.批量删除
删除id为1,2,3的用户
@Test
public void testDeleteByIds(){
userMapper.deleteBatchIds(Arrays.asList(1L,2L,3L));
}
3.条件查询删除
@Test
public void testDeleteByMap() {
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Helen");
map.put("age", 18);
int result = userMapper.deleteByMap(map);
System.out.println(result);
}
4.逻辑删除
物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍 旧能看到此条数据记录
1)数据库添加字段
ALTER TABLE `user` ADD COLUMN `deleted` boolean
2)实体类添加deleted字段
并加上@TableLogic 注解 和 @TableField(fill = FieldFill.INSERT) 注解
@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;
3)元对象处理器接口添加deleted的insert默认值
@Override
public void insertFill(MetaObject metaObject) {
......
this.setFieldValByName("deleted", 0, metaObject);
}
4)application.properties 加入配置
此为默认值,如果你的默认值和mp默认的一样,该配置可无
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
5)在 MybatisPlusConfig 中注册 Bean
在高版本不需要加这个
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
(6)测试逻辑删除
测试后发现,数据并没有被删除,deleted字段的值由0变成了1
测试后分析打印的sql语句,是一条update
注意:被删除数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作
/**
* 测试 逻辑删除
*/
@Test
public void testLogicDelete() {
int result = userMapper.deleteById(1L);
System.out.println(result);
}
7)测试逻辑删除后的查询
MyBatis Plus中查询操作也会自动添加逻辑删除字段的判断
/**
* 测试 逻辑删除后的查询:
* 不包括被逻辑删除的记录
*/
@Test
public void testLogicDeleteSelect() {
User user = new User();
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
测试后分析打印的sql语句,包含 WHERE deleted=0
SELECT id,name,age,email,create_time,update_time,deleted FROM user WHERE deleted=0
逻辑删除新版本配置
1)配置application.yml
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
2)实体类字段上加上@TableLogic
注解
@TableLogic
private Integer deleted;
其他功能
主键策略
1.自动增长 AUTO INCREMENT
分表 id 1-10000 id 10001-20000 id 20001- 30000
2.UUID 每次生产随机唯一的值
缺点:排序不方便
3.redis实现
4.mp自带策略(snowflake雪花算法 )
@Tabled(type=IdType.AUTO)
private long id;
type
AUTO 自动增长
INPUT:设置id值
NOTE:输入
UUID:随机唯一值
ID_WORKER mp自带策略,生成19位值,数字类型使用这种策略,比如long
ID_WORKER_STR mp自带策略,生成19位值,字符串类型使用这种策略,比如String
自动填充
准备
1.表添加两个字段 create_time update_time (datetime类型)
2.添加实体类的属性 命名特点(驼峰)
@Test
public void adduser(){
User user =new User();
user.setName("Aimi");
user.setAge(30);
user.setEmail("Aimi@qq.com");
//手动设置时间值
user.setCreateTime(new Date());
user.setUpdateTime(new Date());
int insert = userMapper.insert(user);//insert 记录影响的函数
System.out.println("insert:"+insert);
}
不需要set到对象里面值,使用mp方式实现数据添加
实现过程:
1)在实体类里面进行自动填充属性添加注解
//驼峰规则,当数据库表中的属性名有_,
// 则在实体类定义时,去掉_,并将_后面的字母大写
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
2) 创建类,实现接口MetaObjectHandler
实现接口里面的方法
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//使用mp实现添加操作,这个方法执行
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//使用mp实现修改操作,这个方法执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
乐观锁
主要解决 丢失更新
如果不考虑事务隔离性,产生读问题?
脏读 不可重复读 幻读
写问题:丢失更新问题(并发改数据)
丢失更新(多个人同时修改同一条记录,最后提交的把之前提交数据覆盖)
实现方法:
1)在数据库的表中加version字段,作为乐观锁版本号
事务并发进行时:比较当前数据版本和数据库版本是否一样 ,把版本号+1
2)对应实体类添加版本属性,并添加注解
@Version private Integer version;//版本号
3)配置乐观锁插件
@Configuration
@MapperScan("com.example.mpdemo.mapper")
public class MpConfig {
//乐观锁插件
//旧版
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
//新版
// @Bean
// public MybatisPlusInterceptor mybatisPlusInterceptor() {
// MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// return interceptor;
// }
}
然后在 MyMetaObjectHandler 的insertFill中添加
this.setFieldValByName("version",1,metaObject);
乐观锁测试
@Test
public void adduser(){
User user =new User();
user.setName("小明");
user.setAge(13);
user.setEmail("Ming@qq.com");
userMapper.insert(user);
}
@Test
public void testOptimisticlocker(){
//根据id查询数据
User user=userMapper.selectById(1442670859910148098L);
//修改
user.setAge(999);
userMapper.updateById(user);
}