hibernate跨資料庫,columnDefinition不可移植性改造方案

·志堅行遠·發表於2023-03-06

背景&問題描述

很多專案選擇jpa/hibernate,更多是為了程式碼的可移植性,不限制資料庫的選擇。特別是toB的業務系統,不同的客戶,要求用不同的資料庫。特別近幾年,大力倡導軟體國產化,國產資料庫也在崛起,很多政府、國企、電力、銀行在資料庫的選擇上,紛紛轉向國產資料庫。也許mybatis+mysql很香,但是程式碼可移植性卻成了toB\toG軟體類平臺的關鍵競爭力。
hibernate,在欄位定義,很多人都喜歡用columnDefinition註解去定義表的DDL,可能是曾經留下來的習慣吧。以前的hibernate對資料庫欄位及資料庫移植性支援的比較差,像json、time、blob等一些特殊欄位型別,表欄位註釋等支援的不好,為了方便,大家基本都會用columnDefinition註解直接去定義表,columnDefinition註解屬性定義的ddl是不可移植性的,導致了整個專案不能跨資料庫自動建立表。
下文講解columnDefinition欄位的替代方案。

解決方案

以mysql為例


@Colum(columnDefinition="decimal(15,2) comment '產品單價' default 1.5 ")

  • 欄位註釋
    需要將hibernate升級到5.6版本以上
    欄位註釋使用註解org.hibernate.annotations.Comment
    @Comment("產品單價")
  • 欄位長度、精度
    欄位長度使用javax.persistence.Column註解中的length屬性,精度使用scale
    @Column(length=15,scale=2)
  • 欄位預設值
    欄位預設值使用org.hibernate.annotations.ColumnDefault註解
    注意:字元型,需要加單引號
    @ColumnDefault("1.5")
  • 大欄位型別
    大欄位處理用javax.persistence.Lob,同時加註解@javax.persistence.Basic(fetch = FetchType.LAZY)懶載入,避免載入大資料,導致效能很差
    對應資料庫text\blob欄位等
    @Column
    @Lob
    @Basic(fetch = FetchType.LAZY)
  • 時間類
    時間型別欄位使用註解javax.persistence.Temporal
    透過傳入註解引數TemporalType型別,可以指定時間型別
    image

@Temporal(TemporalType.TIMESTAMP) // 時間戳
@Temporal(TemporalType.DATE) // 日期
@Temporal(TemporalType.TIME) // 時間

  • json型別
    json資料,如果資料庫不支援json型別,hibernate會預設轉為varchar型別,並且長度預設為255,對於json資料,通常都是大欄位,下期將改造方案。
@TypeDef(name = "json", typeClass = JsonStringType.class)
public class Test {
  @Type(type = "json")
  private TestModel testModel;
}

@Type(type = "json") 其含義是將當前表格列對映成“Hibernate Types”中的 JsonStringType型別。JsonStringType進一步將對應的資料實體對映成VARCHAR型別。

hibernate支援json欄位型別,可參考
https://github.com/vladmihalcea/hibernate-types

注意事項

  • 漢字編碼長度不同
    不同資料庫編碼對字元長度的定義不一致,比如,mysql,varchar(20)可以存放20個漢字,而sqlserver相同的欄位定義只能存放10個漢字。建議在定義表欄位時,取大不取小,考慮漢字佔位符;
  • 批次操作限制
    SqlServer批次入庫不能超過2100條,而mysql沒有此限制。在有批次入庫操作,需要分批入庫處理;
  • 引數限制
    SqlServer傳參不能超過1000個,對於一些表引數傳遞,儘可能用關聯查詢,推薦使用querydsl做關聯查詢,避免大量引數傳遞
  • 唯一鍵名稱重複限制
    mysql中,唯一鍵就是索引,在同一個表,索引名稱不能重複,而SqlServer是有唯一鍵,是整庫內,所有唯一鍵名稱不能重複。建議在建唯一鍵時,不填寫索引name,hibernate會自動生產不重複name
    @Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"name", "age"})})

原文地址:https://www.cnblogs.com/luze/p/17179221.html

相關文章