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

mai*_*rgs 5 java annotations hibernate jpa hsqldb

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

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

我希望能够将Postgres的本机UUID类型与Hibernate一起使用,并在其字符串表示中使用UUID和HSQL进行单元测试(因为HSQL没有UUID类型).

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

这是我如何让Hibernate"看到"我的自定义UserType:

@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;
}
Run Code Online (Sandbox Code Playgroud)

这很有效.但我需要的是能够在XML中替换注释的"com.xxx.UUIDStringType"部分,或者从可以在不重新编译的情况下更改的属性文件.

有任何想法吗?

Phi*_*ppe 9

Hy,对于那些在Hibernate 4中寻求解决方案的人来说(因为Dialect#addTypeOverride方法不再可用),我找到了一个,这是Steve Ebersole评论的基础

您必须构建一个像这样的自定义用户类型:

public class UUIDStringCustomType extends AbstractSingleColumnStandardBasicType {

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

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

}
Run Code Online (Sandbox Code Playgroud)

要将它绑定到HSQLDB方言,您必须构建一个覆盖Dialect#contributionTypes方法的自定义方言,如下所示:

public class CustomHsqlDialect extends HSQLDialect {


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

}
Run Code Online (Sandbox Code Playgroud)

然后,您可以将@Type(type ="pg-uuid")与两个数据库一起使用.

希望它会帮助别人......

  • spring.jpa.properties.hibernate.dialect = com.yourpackage.etc.CustomHsqlDialect (2认同)

Tim*_*Tim 6

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

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

package-info.java只需在您的domain包中创建两个即可。

确保包信息文件始终位于同一个包中(用于测试和生产)。请参阅下面的示例:

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

src/test/java
  app
    package
      domain
        package-info.java 
Run Code Online (Sandbox Code Playgroud)

您制作的内容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;
Run Code Online (Sandbox Code Playgroud)

这就是您测试“配置”的方式(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;
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你


ste*_*vls 5

这个问题确实很老了,已经回答了很长时间,但是最近我也遇到了同样的情况,并且找到了一个很好的解决方案。首先,我发现Hibernate具有三种不同的内置UUID类型实现:

  1. binary-uuid :将UUID存储为二进制
  2. uuid-char :将UUID存储为字符序列
  3. pg-uuid :使用本地Postgres UUID类型

这些类型默认情况下已注册,并且可以为带@Type注释的给定字段指定,例如

@Column
@Type(type = "pg-uuid")
private UUID myUuidField;
Run Code Online (Sandbox Code Playgroud)

还有也是在覆盖默认类型的机制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";
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,只需插入自定义方言,该pg-uuid类型就可以在两种环境中使用。

  • 我没有看到在该类中调用`addTypeOverride`。我正在使用Hibernate 5。 (3认同)