Spring Data JPA自動生成表時列順序混亂的解決辦法(最新版)

程序猿DD發表於2024-11-27

最近把Spring Boot的版本升級到了3.3.5,突然發現一個問題:當使用Spring Data JPA自動生成表的時候,所產生的列順序與Entity類中的變數順序不一致了。比如,有一個下面這樣的Entity:

@Data
@Entity(name = "t_config")
@EntityListeners(AuditingEntityListener.class)
public class Config {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(length = 20)
    private String itemKey;
    @Column(length = 200)
    private String itemValue;
    @Column(length = 200)
    private String itemDesc;

    @CreatedDate
    private Date createTime;
    @LastModifiedDate
    private Date modifyTime;

}

實際自動建立出來的是這樣的:

自動建立的表結構中各個列與Entity類中的變數順序不一致。其實該問題是一個老生常談的問題了,在DD這次升級的工程裡是有做過解決方案的。只是升級了Spring Boot版本之後,之前的解決方案失效了。

搜尋了一番,同時還問了一下AI,發現給出的方案還都是老的解決方案,所以今天特別寫一篇來記錄下新版本之下,要如何解決這個問題。如果您剛好遇到類似的問題,可以參考本文來解決。

老版本解決方案

新老版本的解決思路是類似的,都是替換Hibernate的實現,下面是老版本的解決步驟:

  1. 在工程中新建org.hibernate.cfg
  2. 找到hibernate-core包下的org.hibernate.cfg下的PropertyContainer類,複製到本工程的org.hibernate.cfg包下
  3. PropertyContainer類中定義的persistentAttributeMap型別從TreeMap修改為LinkedHashMap

新版本解決方案

雖然之前的方案失效了,但思路應該還是對的,所以第一反應是看看當前版本下的PropertyContainer類,具體如下(省略了一些不重要的內容):

package org.hibernate.boot.model.internal;

//省略...

public class PropertyContainer {

    private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, PropertyContainer.class.getName());

    /**
     * The class for which this container is created.
     */
    private final XClass xClass;
    private final XClass entityAtStake;

    /**
     * Holds the AccessType indicated for use at the class/container-level for cases where persistent attribute
     * did not specify.
     */
    private final AccessType classLevelAccessType;

    private final List<XProperty> persistentAttributes;

	//省略...

}

可以看到有兩個重要變化部分:

  1. PropertyContainer類的包名從org.hibernate.cfg改到了org.hibernate.boot.model.internal
  2. 之前的TreeMap<String XProperty> persistentAttributeMap變數沒有了,但多了一個List<XProperty> persistentAttributes。進一步觀察這個新變數的處理過程,可以看到如下邏輯:

所以,新版的方案就以下兩個步驟:

  1. 在工程中新建org.hibernate.boot.model.internal
  2. 找到hibernate-core包下的org.hibernate.boot.model.internal下的PropertyContainer類,複製到本工程的org.hibernate.boot.model.internal包下
  3. PropertyContainer類中,上面圖中紅色圈出部門定義的localAttributeMap = new TreeMap<>();修改為localAttributeMap = new LinkedHashMap<>();

到這裡,在新版本中的這個問題就解決了。如果你也遇到了類似的問題,希望本文對你有所幫助。另外,歡迎加入我們的Spring技術交流群,參與交流與討論,更好的學習與進步!

歡迎關注我的公眾號:程式猿DD。第一時間瞭解前沿行業訊息、分享深度技術乾貨、獲取優質學習資源

相關文章