针对 MySQL 在 Hibernate 实体中建模 UUID

Modeling UUID in Hibernate entity against MySQL

我有一个与 this one 非常 相似的问题,但是我的问题比那个问题更基础,所以我 不觉得 就像一个骗局......(我们会看到 SO 的想法)。 如果它是另一个问题的骗局,请向我指出(也许在评论中)接受的答案如何完全 answers/addresses 我的问题(我不这么认为!)。


我有一个 Java/JPA/Hibernate @Entity class 需要一个 UUID 字段:

@Canonical
@MappedSuperclass
public abstract class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private UUID refId;

    // Getters/setters/ctors/etc.
}

@Entity(name = "accounts")
@AttributeOverrides({
    @AttributeOverride(name = "id", column=@Column(name="account_id")),
    @AttributeOverride(name = "refId", column=@Column(name="account_ref_id"))
})
public class Account extends BaseEntity {
    // blah whatever
}

也就是说,我需要在应用程序层使用 UUID。然而,这里的数据库是 MySQL,在 MySQL 中表示 UUID 的压倒性建议似乎是将它们表示为 VARCHAR(36),这就是我所拥有的。

在运行时出现以下异常:

Caused by: org.hibernate.HibernateException: Wrong column type in my_db.accounts for column account_ref_id. Found: varchar, expected: binary(255)
    at org.hibernate.mapping.Table.validateColumns(Table.java:373)
    at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1338)
  <rest of stack trace omitted for brevity>

所以 很明显,数据库显示 VARCHAR(36),但 Hibernate 似乎默认期望 binary(255)

老实说,我不关心 UUID 在数据库中的存储方式。它可能是 VARCHAR,它可能是 TEXT,它可能是 BLOB...它可能是我所关心的烤箱!但这里的本质要求是数据模型(实体class)使用UUIDs.

这里有什么解决方法?如果我必须更改数据库中的列类型,我应该将类型更改为什么?如果我必须 change/modify 实体中的 UUID 字段,我还需要用什么来注释它?

像这样尝试:

    public class BaseEntity{

    @Column(nullable = false)
    private String uuid;

    public BaseEntity(){
         setUuid(UUID.randomUUID().toString());
    }   

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

  @PrePersist
    public void prePersist(){

        if(null == getUuid())
             setUuid(UUID.randomUUID().toString());
 }

    ....

列定义:

uuid varchar(255) DEFAULT NULL

生成UUID时使用toString方法:

entity.setUuid(UUID.randomUUID().toString())

对我来说,修复需要更改数据库架构和实体 (Java) 代码。

首先,我将 CREATE TABLE 语句更改为使用 BINARY(255) 而不是 VARCHAR(36):

CREATE TABLE IF NOT EXISTS accounts (
    # lots of fields...

    account_ref_id BINARY(255) NOT NULL,

    # ...lots of other fields
);

接下来我在实体中的字段声明中添加了 @Type(type="uuid-binary")

@Canonical
@MappedSuperclass
public abstract class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Type(type="uuid-binary")
    private UUID refId;

    // Getters/setters/ctors/etc.
}

@Entity(name = "accounts")
@AttributeOverrides({
    @AttributeOverride(name = "id", column=@Column(name="account_id")),
    @AttributeOverride(name = "refId", column=@Column(name="account_ref_id"))
})
public class Account extends BaseEntity {
    // blah whatever
}

这对我来说效果很好。