2009-06-17 101 views
3

我正在使用Hibernate + JPA作爲我的ORM解決方案。在不同情況下使用不同的Hibernate用戶類型

我使用HSQL進行單元測試,使用PostgreSQL作爲真實數據庫。

我希望能夠使用Postgres的本地UUID類型與Hibernate,並使用HSU的字符串表示形式的UUID進行單元測試(因爲HSQL沒有UUID類型)。

我正在使用具有不同配置的持久性XML用於Postgres和HSQL單元測試。

這裏是我已經休眠「看到」我的自定義用戶類型:

@Id 
@Column(name="UUID", length=36) 
@org.hibernate.annotations.Type(type="com.xxx.UUIDStringType") 
public UUID getUUID() { 
    return uuid; 
} 


public void setUUID(UUID uuid) { 
    this.uuid = uuid; 
} 

和偉大工程。但我需要的是能夠將XML中註釋的「com.xxx.UUIDStringType」部分或可以在不重新編譯的情況下更改的屬性文件。

任何想法?

回答

2

這個問題真的很老,已經回答了很長時間,但我最近發現自己處於這種相同的情況,並找到了一個很好的解決方案。對於初學者來說,我發現了Hibernate有三種不同的內置UUID類型的實現:

  1. binary-uuid:存儲UUID爲二進制
  2. uuid-char:存儲UUID作爲一個字符序列
  3. pg-uuid:使用本機Postgres UUID類型

這些類型是默認註冊的,可以通過@Type註釋爲給定字段指定,例如

@Column 
@Type(type = "pg-uuid") 
private UUID myUuidField; 

機制在Dialect覆蓋默認類型。因此,如果最終部署是跟一個Postgres數據庫,但單元測試使用HSQL,你可以重寫pg-uuid類型通過編寫自定義的方言像這樣讀/寫的字符數據:

public class CustomHSQLDialect extends HSQLDialect { 

    public CustomHSQLDialect() { 
     super(); 

     // overrides the default implementation of "pg-uuid" to replace it 
     // with varchar-based storage. 
     addTypeOverride(new UUIDCharType() { 
      @Override 
      public String getName() { 
       return "pg-uuid"; 
      } 
     }); 
    } 
} 

現在只需要插入在自定義方言中,並且pg-uuid類型在兩種環境中均可用。

2

也許你可以在你的用戶類型中創建一些智能來根據數據庫功能做正確的事情。 Hibernate本身採用了與其「本地」ID生成器類似的方法,根據您使用的數據庫類型,其行爲有所不同。像這樣的方法消除了在運行時切換映射的需要。

例如,您可以爲每個數據庫創建一個strategy類。然後在您的用戶類型類中,檢測您第一次被調用時連接到的數據庫,爲該數據庫實例化適當策略,然後將所有調用委託給策略對象。

+0

謝謝你..你是一個拯救生命的人。戰略模式像一個魅力。 – systemoutprintln 2009-06-17 14:28:04

5

海蘭,對於那些誰正在尋求在Hibernate中4溶液(因爲方言#addTypeOverride方法是沒有更多可用的),我發現一個,就this Steve Ebersole's comment

你必須建立一個自定義的用戶根本鍵入像這樣的:

public class UUIDStringCustomType extends AbstractSingleColumnStandardBasicType { 

    public UUIDStringCustomType() { 
     super(VarcharTypeDescriptor.INSTANCE, UUIDTypeDescriptor.INSTANCE); 
    } 

    @Override 
    public String getName() { 
     return "pg-uuid"; 
    } 

} 

並將其綁定到HSQLDB話,你必須建立一個自定義的方言覆蓋方言#contributeTypes方法是這樣的:

public class CustomHsqlDialect extends HSQLDialect { 


    @Override 
    public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { 
     super.contributeTypes(typeContributions,serviceRegistry); 
     typeContributions.contributeType(new UUIDStringCustomType()); 
    } 

} 

然後您可以對兩個數據庫使用@Type(type =「pg-uuid」)。

希望這將幫助別人......

+0

如何將HSQLDialect鏈接到JPA? – delucasvb 2016-04-26 09:48:21

2

爲了避免UUID類型之間的問題,而無需指定@Type註釋(這基本上意味着你必須調整所有註釋,當你想從Postgres的改變MySQL或其他繞過...)我正在使用package-info.java以及該軟件包上的冬眠@TypeDef註釋。

下面是您的應用程序的示例設置:
假設module/src/main/java/app.package.domain包含您的實體。你的測試存儲在module/src/test/java/app.package

只需在domain包中創建兩個package-info.java即可。

確保package-info文件始終位於相同的包中(用於測試和生產)。請參見下面的下面的例子:

src/main/java 
    app 
    package 
     domain 
     package-info.java 

src/test/java 
    app 
    package 
     domain 
     package-info.java 

你的內容是生產package-info.java應該像這樣(的Postgres):

@TypeDef(
    name = "pg-uuid", 
    defaultForType = UUID.class, 
    typeClass = PostgresUUIDType.class 
) 
package app.package.domain; 

import org.hibernate.annotations.TypeDef; 
import org.hibernate.type.PostgresUUIDType; 

import java.util.UUID; 

這是找你的測試「配置」應該怎麼看起來像(H2):

@TypeDef(
    name = "uuid-char", 
    defaultForType = UUID.class, 
    typeClass = UUIDCharType.class 
) 
package app.package.domain; 

import org.hibernate.annotations.TypeDef; 
import org.hibernate.type.UUIDCharType; 

import java.util.UUID; 

希望它有助於

相關問題