1. 程式人生 > >【mybatis-plus】主鍵id生成、欄位自動填充

【mybatis-plus】主鍵id生成、欄位自動填充

### 一、主鍵id的生成 資料庫表裡通常都會有一個主鍵id,來作為這條資料的唯一標識。 #### 常見的方式 1. 資料庫自動增長 這種很常見了,可以做到全庫唯一。因為id是天然排序的,對於涉及到排序的操作會很方便。 2. UUID 上面的自動增長,雖然簡單,但是對於分表這樣的操作來說就比較麻煩。因為你在第二張插入資料的時候,需要拿到上一張表最後一個數據的id。 UUID則不同,每次都一個隨機唯一的值,不過因為是隨機,所以也就沒有排序了。 3. redis redis也可以用來生成id,利用redis的原子操作。好處是可以不依賴資料庫,效能好,但是隨之因為redis的引入,帶來了一定的複雜度。 #### mybatis-plus的方式 其實在之前使用mp進行新增資料的時候,我並沒有進行對應的配置,預設就會帶有主鍵id。 ![](https://img2020.cnblogs.com/blog/1268169/202012/1268169-20201225114324464-485605341.png) 對其配置也很簡單,在主鍵上加註解,`@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`的幾個列舉值。 ![](https://img2020.cnblogs.com/blog/1268169/202012/1268169-20201225114953877-1336415341.png) * `AUTO`:就是利用資料庫自增了 * `NONE`:未設定,需要手動設定值 * `INPUT`: 需要手動設定值 * `UUID`:生成UUID型別的主鍵id * `ID_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("[email protected]"); userMapper.insert(user); } ``` 執行成功後檢視資料庫表: ![](https://img2020.cnblogs.com/blog/1268169/202012/1268169-20201225121517859-1880591721.png) 新增的時候,2個欄位都填充了時間。 那現在只做更新操作的時候,只會去更新update_time。 ``` // 修改 @Test void updateUser() { User user = new User(); user.setId(1342322873243996161L); user.setName("老王修改後"); userMapper.updateById(user); } ``` ![](https://img2020.cnblogs.com/blog/1268169/202012/1268169-20201225121737372-1306012954.png) 結果正確。