@TableName:设置实体类映射表名
若实体类类型的类名和要操作的表的表名不一致
在实体类类型上添加@TableName("**_***"),标识实体类对应的表,即可成功执行SQL语句
@TableName("t_company_audit")
public class CompanyAudit{
}
@TableId:设置实体类映射表的主键id
MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认
基于雪花算法的策略生成id
若实体类和表中表示主键的不是id,而是其他字段,例如uid
在实体类中uid属性上通过@TableId将其标识为主键,即可成功执行SQL语句
(默认 主键策略 IdType.ASSIGN_ID 雪花算法)
@TableName("t_company_audit")
public class CompanyAudit{
//默认IdType.ASSIGN_ID 雪花算法
@TableId
private Integer uid;
}
id自增 id自增 数据库里的字段也需要设置成自增
@TableName("t_company_audit")
public class CompanyAudit{
//AUTO id自增 数据库里的字段也需要设置成自增
@TableId(value="id",type= IdType.AUTO)
private Integer id;
}
配置全局主键策略:
mybatis-plus:
configuration:
# 配置MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 配置MyBatis-Plus操作表的默认前缀
table-prefix: t_
# 配置MyBatis-Plus的主键策略
id-type: auto
数据库分表:垂直或水平分表
垂直分表
垂直分表适合将表中某些不常用且占了大量空间的列拆分出去。
水平分表
水平分表相比垂直分表,会引入更多的复杂性,例如要求全局唯一的数据id该如何处理
主键自增:①以最常见的用户 ID 为例,可以按照 1000000 的范围大小进行分段, 1 ~ 999999 放到表 1 中, 1000000 ~ 1999999 放到表 2 中,以此类推。②复杂点:分段大小的选取。分段太小会导致切分后子表数量过多,增加维护复杂度;分段太大可能会 导致单表依然存在性能问题,一般建议分段大小在 100 万至 2000 万之间,具体需要根据业务选取合适 的分段大小。③优点:可以随着数据的增加平滑地扩充新的表。例如,现在的用户是 100 万,如果增加到 1000 万, 只需要增加新的表就可以了,原有的数据不需要动。④缺点:分布不均匀。假如按照 1000 万来进行分表,有可能某个分段实际存储的数据量只有 1 条,而 另外一个分段实际存储的数据量有 1000 万条。
取模:①同样以用户 ID 为例,假如我们一开始就规划了 10 个数据库表,可以简单地用 user_id % 10 的值来 表示数据所属的数据库表编号,ID 为 985 的用户放到编号为 5 的子表中, ID 为 10086 的用户放到编号 为 6 的子表中。②复杂点:初始表数量的确定。表数量太多维护比较麻烦,表数量太少又可能导致单表性能存在问题。③优点:表分布比较均匀。④缺点:扩充新的表很麻烦,所有数据都要重分布。
雪花算法 :①核心思想:长度共 64bit (一个 long 型)。首先是一个符号位, 1bit 标识,由于 long 基本类型在 Java 中是带符号的,最高位是符号位,正数是 0 ,负数是1 ,所以 id 一般是正数,最高位是 0 。41bit时间截 ( 毫秒级 ) ,存储的是时间截的差值(当前时间截 - 开始时间截 ) ,结果约等于 69.73 年。10bit作为机器的 ID (5个 bit 是数据中心, 5 个 bit 的机器 ID ,可以部署在 1024 个节点)。12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID )。
②优点:整体上按照时间自增排序,并且整个分布式系统内不会产生 ID 碰撞,并且效率较高。
@TableField:设置实体类字段映射的表的字段名
如果实体类中的属性名和字段名不一致的情况 (@TableField("username"))
@TableName("t_company_audit")
public class CompanyAudit{
//AUTO id自增 数据库里的字段也需要设置成自增
@TableId(value="id",type= IdType.AUTO)
private Integer id;
@TableField("username")
private String name;
}
@TableLogic :逻辑删除
1.数据库中创建逻辑删除状态列 is_delete,设置默认值为0
2.实体类中添加逻辑删除属性
isDelete
@TableName("t_company_audit")
public class CompanyAudit{
//AUTO id自增 数据库里的字段也需要设置成自增
@TableId(value="id",type= IdType.AUTO)
private Integer id;
@TableField("username")
private String name;
@TableLogic(value = "1",delval = "-1") //存在为1 删除为-1 如果不设置 存在默认为0
private Integer isDelete;
}
3.测试删除功能,真正执行的是修改
UPDATE t_company_audit SET is_deleted=1 WHERE id=? AND is_deleted=0
4.测试查询功能,被逻辑删除的数据默认不会被查询
SELECT * FROM t_company_audit WHERE is_deleted=0
@Version:乐观锁
1.数据库中创建逻辑删除状态列
version
,默认为0
2.实体类中添加逻辑删除属性
version
@TableName("t_company_audit")
public class CompanyAudit{
//AUTO id自增 数据库里的字段也需要设置成自增
@TableId(value="id",type= IdType.AUTO)
private Integer id;
@TableField("username")
private String name;
@TableLogic
private Integer isDelete;
@Version
private Integer version;
}
3.更新时,version + 1,如果where语句中的version版本不对,则更新失败
添加乐观锁插件配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
悲观锁:行锁
两个A和B事务同时修改一条数据 A先进 B挂着 必须等A的事务全部完成后 B才能执行。
实现方法:
就是在查询该条数据的是sql 后加一个 for update;即可
例:select * from t_company_audit where username="Erica" for update;