CRUD扩展
插入操作
insert 插入
@Test
public void testInsert() {
User user = new User();
user.setName("name");
user.setAge(24);
user.setEmail("511814693@qq.com");
int result = userMapper.insert(user);
System.out.println(result);
System.out.println(user);
}
数据库插入id的默认值为:全局唯一id
主键生成策略
Twitter的snowflake算法
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0,可以说是全球唯一。具体实现的代码可以参看https://juejin.cn/post/6844903631137800200。
更新操作
// 测试更新
@Test
public void testUpdate() {
User user = new User();
user.setAge(28);
user.setId(1L);
int result = userMapper.updateById(user);
System.out.println(result);
System.out.println(user);
}
所有的sql都是自动帮助你动态配置的
自动填充
创建时间,修改时间!这些操作一遍都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:所有的数据库表:gmt_create,gmt_modified几乎所有的表都要配置上!而且需要自动化。
方式一:数据库级别
添加create_time
、update_time
字段
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
`create_time` datetime,
`update_time` datetime,
`version` int(11) DEFAULT '1',
`deleted` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
添加实体类
private Date createTime;
private Date updateTime;
方式二:代码级别
实体类上增加
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
编写处理器
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
}
}
乐观锁
乐观锁:它总是认为不会出现问题,无论干什么不去上锁,如果出了问题,再次更新新值测试。
悲观锁: 它认为总是出现问题,无论干什么都会上锁!再去操作
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
--A
update user set name = "zs",version =version + 1
where id = 2 and version = 1
--B 线程抢先完成,version=2,会导致A修改失败。
update user set name = "zs",version =version + 1
where id = 2 and version = 1
- 字段上加上
@Version
注解
@Version
private Integer version;
- 组件
@EnableTransactionManagement
@MapperScan("com.kuang.mapper")
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
- 测试乐观锁
// 测试乐观锁
@Test
public void testOptimisticLocker() {
// 线程1
User user = userMapper.selectById(1);
user.setAge(28);
user.setId(1L);
user.setEmail("fupeng1");
// 模拟另一个线程插队操作
User user2 = userMapper.selectById(1);
user2.setAge(28);
user2.setId(1L);
user2.setEmail("fupeng2");
userMapper.updateById(user2);
userMapper.updateById(user);
}
分页查询
@EnableTransactionManagement
@MapperScan("com.kuang.mapper")
@Configuration
public class MyBatisPlusConfig {
/**
* 乐观锁插件
*/
@Bean
public MybatisPlusInterceptor optimisticLockerInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
/**
* 分页插件配置
* @return MybatisPlusInterceptor
*/
@Bean
public MybatisPlusInterceptor paginationInnerInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
- 分页测试
@Test
public void testSelectPage() {
Page<User> page = new Page<>(1,5);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
}
运行结果打印
逻辑删除
- 物理删除: 从数据库中直接移除。
- 逻辑删除:在数据库中没有真正的删除,而是用一个变量让它失效!deleted=0 => deleted = 1
管理员可以查看被删除的记录!防止数据的丢失,类似回收站
- 在数据库表中增加一个
deleted
字段 - pojo实体类中增加
deleted
字段
@TableLogic
private Integer deleted;
- 测试逻辑删除
@Test
public void testDeleteById() {
userMapper.deleteById(1374634848785842177L);
}
4.测试结果其实执行的是update操作