1、@TableName
当使用Mybatis-Plus实现基本的CRUD时,若没有指定要操作的表,操作的表会默认为BaseMapper的泛型实体类所表示的表
例如 XxxMapper extends BaseMapper ,此时操作的表为user表
结论:MyBatis-Plus确定操作的表时,由BaseMapper的泛型决定,即实体类型决定,且默认操作的表名和实体类型的类名一致。
问题
若我需要操作的表为t_person,和实体类类名不一致,那我还能正常操作嘛?
答案是不行!当表名和实体类名不一致时,程序抛出异常,Table ‘mybatis_plus.user’ doesn’t exist
通过@TableName解决问题
在实体类类型上添加@TableName(“t_user”),标识实体类对应的表,即可成功执行SQL语句
通过全局配置解决问题
若遇到实体类对应的表都有固定的前缀,例如t_或者tbl_
此时,可以使用MyBatis-Plus提供的全局配置,为实体类对应的表名设置默认的前缀,此时不需要在实体类上通过@TableName标识实体类对应的表
mybatis-plus:
configuration:
# 配置MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 配置MyBatis-Plus操作表的默认前缀
table-prefix: t_
2、@TableId
经过以上的测试,MyBatis-Plus在实现CRUD时,默认将id作为主键列,插入数据时,默认基于雪花算法策略生成id
问题
若实体类和表中表示主键的不是id,而是其他字段,例如uid,MyBatis-Plus会自动识别uid为主键列吗?
当然不会!程序会抛出异常,Field ‘uid’ doesn’t hava a default value 说明MyBatis-Plus没有将uid作为主键赋值
通过@TableId解决问题
在实体类uid属性上通过@TableId将其标识为主键,即可成功执行SQL语句
@TableId的value属性
若实体类中主键对应的属性为id,而表中表示主键的字段为uid,此时若在属性id上添加注解@TableId,则抛出异常 Unknown Column ‘id’ in ‘field list’, 即MyBatis-Plus仍然会将id作为表的主键操作,而表中表示主键的字段是uid
此时需要通过@TableId注解的value属性,指定表中的主键字段,@Table(“uid”)或者@TableId(value=“uid”)
@TableId的type属性
type属性用来定义主键策略
常用的主键策略:
配置全局主键策略
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
雪花算法
背景
- 当数据规模增长到一定的程度,要应对逐渐增长的访问压力和数据量。
- 数据库的扩展主要方式:业务分库、主从复制、数据库分表。
数据库分表
当业务的单表数据达到单台数据库服务器的处理瓶颈时,需要对单表数据进行拆分。
单表数据拆分有两种方式:垂直分表和水平分表。
垂直分表
垂直分表适合将表中某些==不常用且占了大量空间的列(字段)==拆分出去。
例如:一个student表,含有name,age,gender,address,parents等字段,但是一般查询时只需要知道学生的姓名、年龄和性别就可以了,这时候可以将address、parents等字段拆分出去。
水平分表
水平分表适合行数特别大的表,当表的数据量达到千万级别时,很可能是架构的性能瓶颈或者隐患。
水平分表相比垂直分表,会更加复杂,例如要求全局唯一的数据id如何处理
主键自增
用户id为例子:1-999999放到表1,1000000-1999999放到表2
复杂点:分段大小的选取。分段太小会导致切分后子表数量过多,增加维护复杂度;分段太大可能会
导致单表依然存在性能问题,一般建议分段大小在 100 万至 2000 万之间,具体需要根据业务选取合适
的分段大小。
优点:可以随着数据的增加平滑地扩充新的表。例如,现在的用户是 100 万,如果增加到 1000 万,
只需要增加新的表就可以了,原有的数据不需要动。
缺点:分布不均匀。假如按照 1000 万来进行分表,有可能某个分段实际存储的数据量只有 1 条,而
另外一个分段实际存储的数据量有 1000 万条。
取模
同样以用户 ID 为例,假如我们一开始就规划了 10 个数据库表(对10取余则可以知道放在哪个表中),可以简单地用 user_id % 10 的值来
表示数据所属的数据库表编号,ID 为 985 的用户放到编号为 5 的子表中,ID 为 10086 的用户放到编号
为 6 的子表中。
复杂点:初始表数量的确定。表数量太多维护比较麻烦,表数量太少又可能导致单表性能存在问题。
优点:表分布比较均匀。
缺点:扩充新的表很麻烦,所有数据都要重分布。
雪花算法
由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性。
核心思想:
长度共64bit(一个long型)
符号位 :1bit,正数为0,负数为1,id为正数,所以一般最高位是0
时间戳 :41bit,时间戳(毫秒级),存储的是时间截的差值(当前时间截 - 开始时间截)
机器id :10bit,机器的id(5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)
序列号 :毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个 ID)。
优点 :整体上按照时间自增排序,整个分布式系统不会产生ID碰撞,效率高。
TableField
当MyBatis-Plus在执行SQL语句时,要保证实体类的属性名和表中的字段名一致
情况1
若实体类的属性使用的是驼峰命名风格(userName),表中使用的是下划线命名风格(user_name)
此时MyBatis-Plus会自动将下划线命名风格自动转化为驼峰命名风格
相当于在MyBatis中配置 mybatis.configuration.mapUnderscoreToCamelCase=true
情况2
若实体类中的属性和表中的字段不满足情况1
例如实体类属性name,表中字段username
此时需要在实体类属性上使用@TableField(“username”)设置属性对应的字段名
@TableLogic
逻辑删除
- 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
- 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库
中仍旧能看到此条数据记录 - 使用场景:可以进行数据恢复
实现逻辑删除
测试
测试删除功能,真正执行的是修改is_deleted字段
UPDATE t_user SET is_deleted=1 WHERE id=? AND is_deleted=0
测试查询功能,查询的数据首要条件是is_deleted字段不为1
SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0