分布式 id 的解决方案有很多:UUID,SnowFlake,TinyID,Uidgenerator,Leaf,Tinyid
来设置主键的策略:
@TableField(fill = FieldFill.INSERT) // 插入的时候自动填充
private LocalDateTime gmtCreate;
@TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新的时候自动填充
private LocalDateTime gmtModified;
属性填充其实可以进行一些优化,考虑一些特殊情况,对于一些不存在的属性,就不需要进行属性填充,对于一些设置了值的属性,也不需要进行属性填充,这样可以提高程序的整体运行效率:
4.1 逻辑删除对应的是物理删除,分别介绍一下这两个概念:
- 物理删除 :指的是真正的删除,即:当执行删除操作时,将数据表中的数据进行删除,之后将无法再查询到该数据
- 逻辑删除 :并不是真正意义上的删除,只是对于用户不可见了,它仍然存在与数据表中
/**
* 逻辑删除属性
*/
@TableLogic
@TableField("is_deleted")
private Boolean deleted;
还是参照《阿里巴巴Java开发手册》第 5 章 MySQL 数据库相关的建议,对于布尔类型变量,不能加 is 前缀,所以我们的属性被命名为 deleted,但此时就无法与数据表的字段进行对应了,
所以我们需要使用 @TableField 注解来声明一下数据表的字段名,而 @TableLogin 注解用于设置逻辑删除属性;此时我们执行删除操作:
4.2 增加了如上注解后,查询时携带了一个条件: is_deleted=0 ,这也说明了 MyBatisPlus 默认 0 为不删除,1 为删除。 若是你想修改这个规定,比如设置-1 为删除,1 为不删除,也可以进行配置,
如下是全局配置,也可以单独一个表一个属性进行配置如mybatisplus逻辑删除基本实现和坑点解决_java_脚本之家 (jb51.net)
mybatis-plus:
global-config:
db-config:
id-type: auto
logic-delete-field: deleted # 逻辑删除属性名
logic-delete-value: -1 # 删除值
logic-not-delete-value: 1 # 不删除值
4.3 我们可以输出 MyBatisPlus 生成的 SQL 来分析一下,在配置文件中进行配置:
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 输出SQL日志
注册分页插件(和下面乐观锁插件在同一个地方注册)-》service使用分页插件提供的功能
乐观锁插件
然后注册乐观锁插件-》MyBatisPlus 已经提供了乐观锁机制,只需要在实体类中使用 @Version 声明版本号属性:
@Configuration
public class MyBatisConfig {
/**
* 注册插件
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
- Wrapper:条件构造器抽象类,最顶端的父类
- AbstractWrapper:查询条件封装抽象类,生成 SQL 的 where 条件
- QueryWrapper:用于对象封装
- UpdateWrapper:用于条件封装
- AbstractLambdaWrapper:Lambda 语法使用 Wrapper
- LambdaQueryWrapper:用于对象封装,使用 Lambda 语法
- LambdaUpdateWrapper:用于条件封装,使用 Lambda 语法
- AbstractWrapper:查询条件封装抽象类,生成 SQL 的 where 条件
通常我们使用的都是 QueryWrapper 和 UpdateWrapper,如下
@SpringBootTest
@MapperScan("com.wwj.mybatisplusdemo.mapper")
class MybatisplusDemoApplicationTests {
@Autowired
private EmployeeMapper employeeMapper;
@Test
void contextLoads() {
// 查询名字中包含'j',年龄大于20岁,邮箱不为空的员工信息
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.like("last_name", "j"); // like可以看到它是对 j 的前后都加上了 % ,若是只想查询以 j 开头的名字,则可以使用 likeRight 方法,若是想查询以 j 结尾的名字,,则使用 likeLeft 方法。
wrapper.gt("age", 20);
wrapper.isNotNull("email");
List<Employee> list = employeeMapper.selectList(wrapper);
list.forEach(System.out::println);
}
}