使用 Java 记录作为 JPA 嵌入
Using Java records as JPA embeddables
我想使用 Java record
s 作为 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 record
与 JPA/Hibernate 一起使用?
实体或可嵌入的,无论如何,记录class在这里都不合适,因为实体及其字段(包括可嵌入的字段)是可修改的。唯一的例外是 Id 字段,但这似乎不是一个足够重要的案例来实现此功能。
一位 Hibernate 开发人员对此进行了解释 here
Java records
具有单个字段 可用于自定义 ID 类型或具有 AttributeConverter
的任何其他值对象。
在实体 class 中,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 进行映射,但这有点麻烦。
我想使用 Java record
s 作为 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 record
与 JPA/Hibernate 一起使用?
实体或可嵌入的,无论如何,记录class在这里都不合适,因为实体及其字段(包括可嵌入的字段)是可修改的。唯一的例外是 Id 字段,但这似乎不是一个足够重要的案例来实现此功能。
一位 Hibernate 开发人员对此进行了解释 here
Java records
具有单个字段 可用于自定义 ID 类型或具有 AttributeConverter
的任何其他值对象。
在实体 class 中,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 进行映射,但这有点麻烦。