使用JPA在PostgreSQL中保留UUID

ehs*_*jan 25 java postgresql uuid hibernate jpa

我试图在PostgreSQL中持久化一个使用UUID作为主键的实体.我已经尝试将其作为简单的UUID持久化:

@Id
@Column(name = "customer_id")
private UUID id;
Run Code Online (Sandbox Code Playgroud)

有了上面的内容,我收到了这个错误:

ERROR: column "customer_id" is of type uuid but expression is of type bytea
Hint: You will need to rewrite or cast the expression.
Position: 137
Run Code Online (Sandbox Code Playgroud)

我也尝试将UUID作为byte []保持无效:

@Transient
private UUID id;

@Id
@Column(name = "customer_id")
@Access(AccessType.PROPERTY)
@Lob
protected byte[] getRowId() {
    return id.toString().getBytes();
}

protected void setRowId(byte[] rowId) {
    id = UUID.fromString(new String(rowId));
}
Run Code Online (Sandbox Code Playgroud)

如果我删除@Lob,我得到的错误与上面发布的错误相同.但是应用@Lob后,错误会略有变化:

ERROR: column "customer_id" is of type uuid but expression is of type bigint
Hint: You will need to rewrite or cast the expression.
Position: 137
Run Code Online (Sandbox Code Playgroud)

我觉得非常糟糕,无法做到这么简单!

我正在使用Hibernate 4.1.3.Final和PostgreSQL 9.1.

我在相同的问题上或多或少地看到过很多关于SO的问题,但是它们都很老,似乎没有一个直截了当的答案.

我希望以一种标准的方式实现这一点,而不是诉诸丑陋的黑客.但如果这只能通过(丑陋的)黑客来实现,那么可能就是我要做的.但是,我不希望将UUID存储为数据库中的varchar,因为这对性能不利.另外,我想在可能的情况下不在代码中引入Hibernate依赖项.

任何帮助将不胜感激.

更新1(2012-07-03 12:15 pm)

嗯,好吧......有点儿,我使用JTDS驱动程序(v1.2.5)和SQL Server 2008 R2测试完全相同的代码(普通UUID,没有转换 - 上面发布的代码的第一个版本) ,猜猜看,它作为一个魅力(当然我必须在persistence.xml中更改与连接相关的信息).

现在,它是PostgreSQL特有的问题还是什么?

Ste*_*ole 34

不幸的是,PostgreSQL JDBC驱动程序选择了表示非JDBC标准类型代码的方法.他们只是将所有这些映射到Types.OTHER.简而言之,您需要启用一个特殊的Hibernate类型映射来处理UUID映射(到postgres特定的uuid数据类型的列):

@Id
@Column(name = "customer_id")
@org.hibernate.annotations.Type(type="org.hibernate.type.PostgresUUIDType")
private UUID id;
Run Code Online (Sandbox Code Playgroud)

或者更简洁:

@Id
@Column(name = "customer_id")
@org.hibernate.annotations.Type(type="pg-uuid")
private UUID id;
Run Code Online (Sandbox Code Playgroud)

另一个(更好的)选项是将org.hibernate.type.PostgresUUIDType注册为公开为java.util.UUID的所有属性的默认Hibernate类型映射.文档@ http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch06.html#types-registry中对此进行了介绍


Ole*_*hin 16

JPA 2.1提供了一种非常简单的方法来使用PostgreSQL uuid列类型以及java.util.UUID相应实体字段的类型:

@javax.persistence.Converter(autoApply = true)
public class PostgresUuidConverter implements AttributeConverter<UUID, UUID> {

    @Override
    public UUID convertToDatabaseColumn(UUID attribute) {
        return attribute;
    }

    @Override
    public UUID convertToEntityAttribute(UUID dbData) {
        return dbData;
    }

}
Run Code Online (Sandbox Code Playgroud)

只需将此类添加到持久性配置中,并使用注释UUID字段@Column(columnDefinition="uuid").


小智 8

要让它与Hibernate 5.1.x一起使用,您可以在此处关注Steve Ebersole的评论

@Id
@GeneratedValue
@Column( columnDefinition = "uuid", updatable = false )
public UUID getId() {
    return id;
}
Run Code Online (Sandbox Code Playgroud)