最近把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類中的變數順序不一致。其實該問題是一個老生常談的問題了,在小編這次升級的工程裡是有做過解決方案的。只是升級了Spring Boot版本之後,之前的解決方案失效了。
搜尋了一番,同時還問了一下AI,發現給出的方案還都是老的解決方案,所以今天特別寫一篇來記錄下新版本之下,要如何解決這個問題。如果您剛好遇到類似的問題,可以參考本文來解決。
老版本解決方案
新老版本的解決思路是類似的,都是替換Hibernate的實現,下面是老版本的解決步驟:
在工程中新建
org.hibernate.cfg
包找到
hibernate-core
包下的org.hibernate.cfg
下的PropertyContainer
類,複製到本工程的org.hibernate.cfg
包下把
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; //省略... }
可以看到有兩個重要變化部分:
PropertyContainer
類的包名從org.hibernate.cfg
改到了org.hibernate.boot.model.internal
之前的
TreeMap<String XProperty> persistentAttributeMap
變數沒有了,但多了一個List<XProperty> persistentAttributes
。進一步觀察這個新變數的處理過程,可以看到如下邏輯:
所以,新版的方案就以下兩個步驟:
在工程中新建
org.hibernate.boot.model.internal
包找到
hibernate-core
包下的org.hibernate.boot.model.internal
下的PropertyContainer
類,複製到本工程的org.hibernate.boot.model.internal
包下把
PropertyContainer
類中,上面圖中紅色圈出部門定義的localAttributeMap = new TreeMap<>();
修改爲localAttributeMap = new LinkedHashMap<>();