一、主鍵id的生成
數據庫表里通常都會有一個主鍵id,來作為這條數據的唯一標識。
常見的方式
-
數據庫自動增長
這種很常見了,可以做到全庫唯一。因為id是天然排序的,對於涉及到排序的操作會很方便。 -
UUID
上面的自動增長,雖然簡單,但是對於分表這樣的操作來說就比較麻煩。因為你在第二張插入數據的時候,需要拿到上一張表最后一個數據的id。
UUID則不同,每次都一個隨機唯一的值,不過因為是隨機,所以也就沒有排序了。 -
redis
redis也可以用來生成id,利用redis的原子操作。好處是可以不依賴數據庫,性能好,但是隨之因為redis的引入,帶來了一定的復雜度。
mybatis-plus的方式
其實在之前使用mp進行新增數據的時候,我並沒有進行對應的配置,默認就會帶有主鍵id。
對其配置也很簡單,在主鍵上加注解,@TableId(type = IdType.ID_WORKER)
@Data
public class User {
@TableId(type = IdType.ID_WORKER)
private Long id;
private String name;
private Integer age;
private String email;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) // 新增的時候update也有值
private Date updateTime;
}
在idea編輯器里,可以按住ctrl+鼠標左擊,看到IdType
的幾個枚舉值。
AUTO
:就是利用數據庫自增了NONE
:未設置,需要手動設置值INPUT
: 需要手動設置值UUID
:生成UUID類型的主鍵idID_WORKER
:生成19位的值,數字類型ID_WORKer_STR
:生成19位的值,字符串類型
關於mp的這個19位值的生成,可以做個了解,利用了snowflake算法。
snowflake是Twitter開源的分布式ID生成算法,結果是一個long型的ID。
其核心思想是:使用41bit作為毫秒數,10bit作為機器的ID(5個bit是數據中心,5個bit的機器ID),
12bit作為毫秒內的流水號(意味着每個節點在每毫秒可以產生 4096 個 ID),最后還有一個符號位,永遠是0。
二、mp實現自動填充
在操作數據庫的時候還有一種常見操作,就是一些字段的填充,比如常見的create_time、update_time等,填充方式都是相同的。
那么除了每次的手動填充,還可以自動填充。而在MP里設置自動填充只要2步即可:
1.添加注解
@TableField(fill = FieldFill.INSERT)
、@TableField(fill = FieldFill.INSERT_UPDATE)
。
@Data
public class User {
@TableId(type = IdType.ID_WORKER)
private Long id;
private String name;
private Integer age;
private String email;
@TableField(fill = FieldFill.INSERT) // 新增的時候填充數據
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) // 新增或修改的時候填充數據
private Date updateTime;
}
2.自定義實現類 MyMetaObjectHandler
這里需要我們自己寫一個實現類
@Component //此注解表示 將其交給spring去管理
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
對了,要在數據庫表里增加對應的字段create_time
、update_time
。添加后可以試一下了,先來新增一條測試數據:
// 新增
@Test
void addUser() {
User user = new User();
user.setName("老王");
user.setAge(66);
user.setEmail("laowang@123.com");
userMapper.insert(user);
}
執行成功后查看數據庫表:
新增的時候,2個字段都填充了時間。
那現在只做更新操作的時候,只會去更新update_time。
// 修改
@Test
void updateUser() {
User user = new User();
user.setId(1342322873243996161L);
user.setName("老王修改后");
userMapper.updateById(user);
}
結果正確。