使用ORM 6映射UUID值

作者:    |       Hibernate ORM

Hibernate ORM 6.0使得映射UUID值变得简单,包括使用生成的UUID值作为标识符。

默认情况下,Hibernate将映射UUID值到以下类型之一:

  • 如果数据库定义了特定的UUID类型,则为数据库特定的UUID类型 - PostgreSQL使用UUID,T-SQL变体使用UNIQUEIDENTIFIER等。

  • 如果数据库没有定义特定的UUID类型,则为BINARY

从技术上讲,Hibernate使用其特殊的SqlTypes.UUID代码进行隐式UUID映射,这表示Hibernate应该选择合适的策略(最终基于底层的Dialect)。

SqlTypes视为JDBC的Types的扩展。它定义了相同的常量并公开了Hibernate以特定方式处理的额外代码(例如SqlTypes.UUID)。

示例1. 隐式UUID映射
@Basic
UUID sku;

在这里,在没有显式映射配置的情况下,Hibernate使用这个特殊的SqlTypes.UUID代码。

Hibernate扩展

但是,假设我们希望总是将此UUID映射到CHAR。Hibernate提供了几种方法来实现这一点。我们可以仅为此单个属性本地配置

示例2. @JdbcTypeCode
@Basic
@JdbcTypeCode(SqlTypes.CHAR)
UUID sku;

在这里,我们已显式配置了在数据库中存储此UUID时使用CHAR

但是,这种方法仅影响我们应用注解的属性。考虑到这种决策通常在整个组织中是一致的,我们可能更希望指定对所有UUID值使用CHAR。Hibernate也支持这一点

示例3. hibernate.type.preferred_uuid_jdbc_type
hibernate.type.preferred_uuid_jdbc_type=CHAR

有了这种配置,所有隐式UUID值映射(包括前面的示例)现在都将映射到SQL CHAR

Jakarta Persistence

也可以使用jakarta.persistence.AttributeConverter以可移植的方式实现相同的效果。

同样,我们可以仅为此特定属性应用此处理

示例 4. @Convert
@Basic
@Convert(UuidConverter.class)
UUID sku;

以及全局应用于所有 UUID 值,通过使 UuidConverter 自动应用

示例 5. @Converter(autoApply=true)
@Converter(autoApply=true)
public class UuidConverter
        implements AttributeConverter<UUID,Character> {
    ...
}

有关使用转换的更多详细信息,请参阅用户指南

使用 AttributeConverter 映射 UUID 有一个主要的缺点……这些属性不能用作标识符,因为 Jakarta Persistence 规范明确指出标识符属性不能进行转换。

标识符生成

Hibernate 已经支持使用 UUID 值作为标识符,并使用生成的 UUID 值作为标识符有一段时间了。

我们上面已经看到了如何映射 UUID 值。让我们看看如何指定值生成。首先是最传统的形式

示例 6. @GenericGenerator
@Id
@GeneratedValue(generator="uuid-generator")
@GenericGenerator(name="uuid-generator", strategy="UuidGenerator.class" )
UUID id;

一个更简化的形式(但没有对生成的控制)

示例 7. @GenericGenerator
@Id
@GeneratedValue
UUID id;

6.0 还增加了一个专用、简化的注解,允许配置

示例 8. @UuidGenerator
@Id
@GeneratedValue
@UuidGenerator
UUID id;

UuidGenerator 支持多种 "生成策略"}

AUTO

默认为 RANDOM

RANDOM

使用 {@link UUID#randomUUID()}

TIME

使用基于时间的生成策略

这些策略都会产生符合 IETF RFC 4122 的值。

对于使用 Jakarta Persistence 3.1 的用户,该版本还增加了一个新的 GenerationType#UUID 枚举

示例 9. GenerationStrategy#UUID
@Id
@GeneratedValue(strategy=UUID)
UUID id;

Jakarta Persistence 注解的缺点是它定义了没有可移植的设施来自定义实际的生成,仅表示提供者 "应分配一个 RFC 4122 通用唯一标识符"。

对于自定义生成策略,我们还可以利用 ORM 6.0 中引入的新 IdGeneratorType 注解

示例 10. @IdGeneratorType
public class CustomUuidGenerator implements IdentifierGenerator {
    ...

    @Override
    Object generate(SharedSessionContractImplementor session, Object object) { ... }
}

@IdGeneratorType( CustomUuidGenerator.class )
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface CustomUuidGeneration {
    // any config to expose to user
}

@Entity
public class TheEntity {
    @Id
    @GeneratedValue
    @CustomUuidGeneration(
            // config here
    )
    UUID id;
}

有关使用 IdGeneratorType 的更多详细信息,请参阅用户指南

Hibernate 还可以为定义为 String 的标识符属性应用基于 UUID 的生成。例如,以下所有映射都是合法的

示例 11. 作为 String 的 UUID 生成
@Id
@GeneratedValue(generator="uuid-generator")
@GenericGenerator(name="uuid-generator", strategy="UuidGenerator.class" )
String id;


@Id
@GeneratedValue
@UuidGenerator
String id;


@Id
@GeneratedValue(strategy=UUID)
String id;

但是,请注意,以下不会生成 UUID 值

示例 12. 作为 String 的 UUID 生成
@Id
@GeneratedValue
String id;

进一步阅读

有关基本值映射的更多详细信息,请参阅基本值用户指南部分。请特别注意关于组合映射的部分,这是 6.0 中新加入的;@JdbcTypeCode 是组合映射的一个示例。

有关标识符生成的更多详细信息,请参阅生成的标识符值使用 UUID 生成用户指南部分。

对于从先前版本迁移的用户,请务必查看迁移指南


返回顶部