2009-06-17 103 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; 

希望它有助于

相关问题