有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在不同情况下使用不同的Hibernate用户类型

我使用Hibernate+JPA作为我的ORM解决方案

我使用HSQL进行单元测试,使用PostgreSQL作为真正的数据库

我希望能够在Hibernate中使用Postgres的原生UUID类型,并在其字符串表示形式中使用UUID和HSQL进行单元测试(因为HSQL没有UUID类型)

我正在使用不同配置的持久性XML进行Postgres和HSQL单元测试

下面是我如何让Hibernate“查看”我的自定义用户类型:

@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”部分,这些属性文件无需重新编译即可更改

有什么想法吗


共 (4) 个答案

  1. # 1 楼答案

    Hy,对于那些正在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”)用于这两个数据库

    希望它能帮助别人

  2. # 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;
    

    还有一种覆盖^{中默认类型的机制。因此,如果最终的部署是与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类型在两种环境中都可用

  3. # 3 楼答案

    为了避免UUID类型之间的问题,而不指定@Type注释(这基本上意味着,当您想要从postgres更改为mysql或其他方式时,必须调整所有注释…)我在这个包上使用了带有hibernates @TypeDef注释的package-info.java

    以下是应用程序的示例设置:
    假设module/src/main/java/app.package.domain包含您的实体。您的测试存储在module/src/test/java/app.package

    只需在domain包中创建两个package-info.java

    Make sure the package-info files are always in the same package (for testing and production). See the following example below:

    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;
    

    希望有帮助

  4. # 4 楼答案

    也许你可以在你的用户类型中建立一些智能,根据数据库功能做正确的事情。Hibernate本身对其“本机”ID生成器采取了类似的方法,根据您使用的数据库类型,它的行为会有所不同。这样的方法不需要在运行时切换映射

    例如,可以为每个数据库创建一个strategy类。然后在用户类型类中,在第一次被调用时检测连接到哪个数据库,为该数据库实例化适当的策略,然后将所有调用委托给策略对象