spring data jpa、Hibernate開啟全球唯一UUID設置
spring data jpa、Hibernate開啟全球唯一UUID設置
原文鏈接:https://www.cnblogs.com/blog5277/p/10662079.html
原文作者:博客園--曲高終和寡
*******************如果你看到這一行,說明爬蟲在本人還沒有發布完成的時候就抓走了我的文章,導致內容不完整,請去上述的原文鏈接查看原文****************
UUID這個東西,具體的我就不講了,網上的內容很多,我這裏就隨便放一個大家看一下就了解了
https://www.jianshu.com/p/d77f3ef0868a
這裏面有關於發號器,UUID的介紹,具體各位是使用UUID的哪個版本,或者使用雪花ID,或者使用其他別的方式,請各位自行判斷
在我的業務裏面呢:
1.準備部署至少兩臺服務器,且兩臺服務器時區不一樣,一臺阿裏雲香港,東八區,一臺美國洛杉磯,多少區忘了,反正有13個小時的時差,
——雪花ID的方案就被我否了,因為我不能保證美國那臺服務器的時區不會根據冬夏令時來回跳,雪花ID在時鐘回撥的情況下會一直等候,我也不需要雪花ID有序這個優點。
2.同樣為了容災,我準備在兩臺服務器分別部署數據庫
——主鍵自增的方案就被我否了,遷移有點麻煩了
3.我不需要主鍵來排序,我選用的PostgresQL也不會因為主鍵是字符型的而導致插入、讀取變快
——所以我不需要一切主鍵需要有序的生成方案,UUID完美符合我的需求
4.既然選用了UUID,我就希望它在任何情況下都不會重復,全球唯一
——那麽UUID的生成方案2.3.4.5就都不滿足我的要求了,雖然概率極地,但是還是有理論上重復的可能性的
5.UUID的方案1存在一定的危險性,是根據MAC地址(或者IP)生成的,那麽理論上能根據MAC地址找到所在地
——。。。然後呢。。。?我一臺服務器/IP在香港,一臺服務器/IP在洛杉磯,想通過這倆地方來找我怕是不太可能嗷。。。更何況我寫的東西根本就不會有多少人用,更沒有什麽法律風險不擔心被查水表,更沒有什麽價值。。。?誰會來搞我?
所以,最終選用了方案1的UUID生成方法,不可能重復,我開發的時候就不用考慮這種極小概率會導致的BUG,放心大膽的用就是了。
而生成方案1的UUID有很多工具包,比如Apache common 的UUID 包,還有github上一個項目 JAU,項目地址:
https://github.com/cowtowncoder/java-uuid-generator
我太懶了,不想在項目裏引入一個包,就為了生成UUID。。。所以就查了一下,原來HIbernate對生成UUID方案1還做了優化:
Version1變種 – Hibernate
Hibernate的CustomVersionOneStrategy.java,解決了之前version 1的兩個問題
- 時間戳(6bytes, 48bit):毫秒級別的,從1970年算起,能撐8925年….
- 順序號(2bytes, 16bit, 最大值65535): 沒有時間戳過了一秒要歸零的事,各搞各的,short溢出到了負數就歸0。
- 機器標識(4bytes 32bit): 拿localHost的IP地址,IPV4呢正好4個byte,但如果是IPV6要16個bytes,就只拿前4個byte。
- 進程標識(4bytes 32bit): 用當前時間戳右移8位再取整數應付,不信兩條線程會同時啟動。值得留意就是,機器進程和進程標識組成的64bit Long幾乎不變,只變動另一個Long就夠了。
Hibernate解決了Version1的兩個問題,哪兩個問題呢:
但好像Version 1就沒考慮過一臺機器上起了兩個進程這類的問題,也沒考慮相同時間戳的並發問題
很好,HIbernate解決了這倆問題,那完美符合我的需求,並且本來項目就引入了JPA,官方支持豈不美哉?
廢話說了那麽多,配置只需要兩行的事,然而這個配置國內網站幾乎找不到,困擾了我很久怎麽在Hibernate裏面設置選用CustomVersionOneStrategy.java,作為主鍵生成策略的
@Entity @Data @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @GenericGenerator( name = "uuid2", strategy = "uuid2", parameters = {@org.hibernate.annotations.Parameter( name = "uuid_gen_strategy_class", value = "org.hibernate.id.uuid.CustomVersionOneStrategy") }) public class BaseDomain { @Id @GeneratedValue(generator = "uuid2") private String id; @Column private LocalDateTime gmtCreate; @Column private LocalDateTime gmtModified; public void initInsert() { this.gmtCreate = LocalDateTime.now(); this.gmtModified = LocalDateTime.now(); } public void initUpdate() { this.gmtModified = LocalDateTime.now(); } }
這樣就可以了,以後每一個DO都繼承這個BaseDomain,ID就自動生成Hibernate優化版的版本1UUID了
spring data jpa、Hibernate開啟全球唯一UUID設置