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,作為主鍵生成策略的

/**
 * @Author:ShadowSaint
 * @Date:19-4-3 上午4:56
 * @Description: TODO
 */
@MappedSuperclass
@Data
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class BaseDomain {
    @Id
    @GenericGenerator(
            name = "uuid2",
            strategy = "uuid2",
            parameters = {@org.hibernate.annotations.Parameter(
                    name = "uuid_gen_strategy_class",
                    value = "org.hibernate.id.uuid.CustomVersionOneStrategy")
            })
    @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了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM