Mybatis-Plus使用(二)操作语法
1. 插入测试及雪花算法
CRUD扩展
Insert插入
@Test
void testInsert(){
User user = new User();
user.setName("levnli").setAge(23).setEmail("levnliservice@126.com");
// 自动生成id
int result = userMapper.insert(user);
// 受影响的行数
System.out.println(result);
// 发现 id 会自动回填
System.out.println(user);
}
数据库插入的id的默认值为:全局唯一的
主键生成策略:雪花算法
-
id自增策略是:ID_WORKER
-
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID,其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一
2. 不同主键策略测试
/**
* 数据库ID自增
*/
AUTO(0),
/**
* 该类型为未设置主键类型
*/
NONE(1),
/**
* 用户输入ID
* 该类型可以通过自己注册自动填充插件进行填充
*/
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 全局唯一ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯一ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯一ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
- 如果想选用策略为:AUTO
- 实体类字段上添加
@TableId(type = IdType.AUTO)
- 数据库字段一定要是自增!
- 实体类字段上添加
- 再次测试插入
3. 更新操作
@Test
void testUpdate(){
User user = new User().setId(1336837066142076930L).setName("test");
int i = userMapper.updateById(user);
System.out.println(i);
}
- 所有的sql都是自动拼接,动态配置的
自动装填
- 创建时间、修改时间!这些操作都是自动化完成的,不希望手动更新
- 所有的数据库表:gmt_create、gmt_modified,几乎所以的表都要配置上,而且需要自动填充
4. 自动填充处理
方式一:数据库级别(工作中不允许修改数据库)
-
在表中新增字段create_time,update_time
ALTER TABLE `mybatis_plus`.`user` ADD COLUMN `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' AFTER `email`, ADD COLUMN `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' AFTER `create_time`;
-
再次测试插入方法,先把实体类同步
-
private Date createTime; private Date updateTime;
-
-
再次更新查看即可
方式二:代码级别
-
删除数据库的默认值、更新操作!
- 去掉时间配置
- ALTER TABLE
mybatis_plus
.user
MODIFY COLUMNcreate_time
datetime(0) NULL COMMENT '创建时间' AFTERemail
,
MODIFY COLUMNupdate_time
datetime(0) NOT NULL COMMENT '更新时间' AFTERcreate_time
;
-
实体类的字段属性上需要增加注解
-
// 字段添加填充内容 @TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime;
-
-
编写处理器,来处理这个注解即可
@Slf4j @Component public class MyMetaObjectHandler implements MetaObjectHandler { /** * 插入时的填充策略 * @param metaObject */ @Override public void insertFill(MetaObject metaObject) { log.info("start insert fill...."); this.setFieldValByName("createTime",new Date(),metaObject); this.setFieldValByName("updateTime",new Date(),metaObject); } /** * 更新时的填充策略 * @param metaObject */ @Override public void updateFill(MetaObject metaObject) { log.info("start updateTime fill...."); this.setFieldValByName("updateTime",new Date(),metaObject); } }
-
测试插入、更新
- 观察时间即可
5. 乐观锁处理详解
-
在面试过程中,经常被问到乐观锁、悲观锁
-
乐观锁
- 十分乐观,不会认为出现问题
- 无论干什么都不会上锁
- 如果出现了问题,再次更新值测试
- version、new version
-
悲观锁
- 十分悲观,总是认为都会出现问题
- 无论干什么都会上锁!再去操作
-
主要讲解乐观锁机制
-
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
乐观锁:先查询,获得版本号version = 1 -- A线程 update user set name = "test" , version = version + 1 where id = 2 and version = 1 -- B线程 update user set name = "test" , version = version + 1 where id = 2 and version = 1 结果B线程抢先完成,这时候version = 2,导致A线程修改失败
测试一下MP的乐观锁插件
-
给数据库中添加version字段
- ALTER TABLE
mybatis_plus
.user
MODIFY COLUMNversion
int(10) NULL DEFAULT 1 COMMENT '乐观锁' AFTERupdate_time
ADD COLUMNversion
int(10) NULL COMMENT '乐观锁' AFTERupdate_time
;
- ALTER TABLE
-
实体类添加对应的字段
-
/** * 乐观锁version注解 */ @Version private Integer version;
-
-
注册组件
@EnableTransactionManagement @MapperScan("com.example.mapper") @Configuration public class MyBatisPlusConfig { // 注册乐观锁插件 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }
-
测试一下
@Test void testOptimisticLocker(){ // 查询用户信息 User user = userMapper.selectById(6L); // 修改用户信息 user.setEmail("123@qq.com"); // 执行更新 userMapper.updateById(user); } @Test void testOptimisticLockerThread(){ // 模拟乐观锁,多线程并发 // 线程1 User user = userMapper.selectById(6L); user.setEmail("111@qq.com"); // 线程2,抢先提交 User user2 = userMapper.selectById(6L); user2.setEmail("222@qq.com"); userMapper.updateById(user2); userMapper.updateById(user); }
6. 查询操作
- 批量查询和条件查询
/**
* 测试批量查询
*/
@Test
void testSelectByIds(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1,2,3));
users.forEach(System.out::println);
}
/**
* 条件查询之一使用 map
*/
@Test
void selectByMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","levnli");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
7. 分页查询实现
- 分页查询在网站使用十分之多!
- 原始的limit进行分页
- pageHelper第三方插件
- MP其实也内置了分页插件
如何使用
-
配置拦截器组件即可
-
// 分页插件 @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); }
-
-
直接使用Page对象即可
-
@Test void testPage(){ // 参数:当前页、页面大小 Page<User> page = new Page<>(2,5); userMapper.selectPage(page,null); // 打印查询结果 page.getRecords().forEach(System.out::println); // 当前表总共条数 System.out.println(page.getTotal()); }
-
8. 删除操作
-
根据ID删除记录
/** * 通过ID删除 */ @Test void testDeleteById(){ userMapper.deleteById(1336837066142076931L); }
-
根据ID批量删除
/** * 通过ID批量删除 */ @Test void testDeleteBatchIds(){ userMapper.deleteBatchIds(Arrays.asList(1336837066142076931L)); }
-
根据条件删除
/** * 通过条件删除 */ @Test void testDeleteMap(){ HashMap<String, Object> map = new HashMap<>(); map.put("name","test2"); userMapper.deleteByMap(map); }
9. 逻辑删除
- 物理删除:从数据库中直接移除
- 逻辑删除:在数据库中没有被移除,而是通过一个变量来让他失效!
- deleted = 0 -> deleted = 1
- 管理员可以查看被删除的记录!防止数据的丢失,类似于回收站
测试一下:
-
在数据报中增加一个
deleted
字段ALTER TABLE `mybatis_plus`.`user` ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '删除标志位' AFTER `version`;
-
在实体类上添加字段
/** * 逻辑删除 */ @TableLogic private Integer deleted;
-
添加插件
// 逻辑删除插件 @Bean public ISqlInjector sqlInjector() { return new LogicSqlInjector(); }
-
配置逻辑删除
mybatis-plus: global-config: db-config: logic-delete-value: 1 logic-not-delete-value: 0
10. 性能分析插件
开发中,会遇到慢sql
MP也提供性能分析插件,如果超过这个时间就是停止运行
-
导入插件
// SQL执行效率插件 @Bean @Profile("dev") public PerformanceInterceptor performanceInterceptor(){ PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor(); // sql最大执行时间,超过不执行 performanceInterceptor.setMaxTime(100); // 输出sql格式化 performanceInterceptor.setFormat(true); return performanceInterceptor; }
-
修改application.yml
spring: profiles: active: dev
-
测试使用
- 执行任何一个方法
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 木子李
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果