2

我想将 Javarecord用作 JPA 的可嵌入对象。例如,我想将 ID 包装在记录中以使其类型安全:

@Entity
public class DemoEntity {

    @EmbeddedId
    private Id id = new Id(UUID.randomUUID());

    @Embeddable
    public static record Id(@Basic UUID value) implements Serializable {}
}

但是如果我尝试使用 Hibernate 5.4.32 坚持它,我会收到以下错误:

org.hibernate.InstantiationException: No default constructor for entity:  : com.example.demo.DemoEntity$Id
    at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:85) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.tuple.component.AbstractComponentTuplizer.instantiate(AbstractComponentTuplizer.java:84) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
...

所以看起来 Hibernate 会像对待record Id实体一样对待它,尽管它是一个@Embeddable.

非 id 字段和 也会发生同样的情况@Embedded

@Embedded
private Thing thing = new Thing("example");

@Embeddable
public static record Thing(@Basic String value) implements Serializable {}

有没有办法将@Embeddable records 与 JPA/Hibernate 一起使用?

4

2 回答 2

1

records 具有单个字段的Java可用于自定义 ID 类型或任何其他带有AttributeConverters 的值对象。

在实体类中,ID 类型@Id照常使用:

@Entity
public class DemoEntity {

    @Id
    private Id id = new Id(UUID.randomUUID());

    public static record Id(UUID value) implements Serializable {}
}

请注意,record Id没有任何注释。

转换器可以使用记录:

@Converter(autoApply = true)
public class DemoEntityIdConverter implements AttributeConverter<DemoEntity.Id, String> {
  
    @Override
    public String convertToDatabaseColumn(DemoEntity.Id id) {
        return id.value().toString();
    }

    @Override
    public DemoEntity.Id convertToEntityAttribute(String s) {
        return new DemoEntity.Id(UUID.fromString(s));
    }
}

不要忘记设置autoApply = true自动应用此转换器(无需在相应字段上明确引用它)。

具有多个字段的记录可以使用 Hibernate UserType 进行映射,但这有点麻烦。

于 2021-07-26T11:00:14.820 回答
0

实体或可嵌入,在任何情况下记录类都不适合这里,因为实体及其字段,包括可嵌入的,是可修改的。唯一的例外是 Id 字段,但这似乎不是一个足够重要的案例来实现此功能。

一位 Hibernate 开发人员在这里解释了这一点

于 2021-07-22T15:33:17.903 回答