我的类中有一个类型为
javax.xml.datatype.Duration
的属性字段。它基本上代表一个时间跨度(例如 4 小时 34 分钟)。
JPA 告诉我这是一个无效类型,这并没有让我感到震惊。
这有什么好的解决方案吗?我可以实现我自己的 Duration 类,但我不知道如何让 JPA“接受”它作为数据类型。
这有什么好的解决方案吗?我可以实现我自己的 Duration 类,但我不知道如何让 JPA“接受”它作为数据类型。
JPA 不支持自定义类型,因此如果您想采用这种方式,则必须使用提供商提供的 JPA 扩展。例如,Hibernate 允许定义使用 @Type
声明的自定义值类型。显然,这将损害提供商之间的可移植性,这可能是一个问题。如果没有,那么您知道这是可行的。
使用标准 JPA,传统方法是添加另一个 getter/setter 对,以适应有问题的属性并在访问时执行转换。我会使用
Long
来存储持续时间:
public MyEntity implements Serializable {
private Long id;
private javax.xml.datatype.Duration duration;
@Id
@GeneratedValue
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
@Transient
public Duration getDuration() {
return this.duration;
}
public void setDuration(Duration duration) {
this.duration = duration;
}
public Long getDurationAsJpaCompatibleType() {
return MyXmlUtil.convertDurationToLong(this.duration);
}
public void setDurationAsJpaCompatibleType(Long duration) {
setDuration(MyXmlUtil.convertLongToDuration(duration));
}
}
您可以将 Duration 类中的确切字段镜像到您自己的自定义类中,但这可能有点矫枉过正......我假设您不需要这种持续时间灵活性/粒度。
因此,选择您想要的字段,将它们添加到您的类中,使用 @Embeddable 注释标记该类,然后将正确的 JPA 注释添加到字段中(我假设这将是简单的整数)。
在要存储持续时间的实体中,将 @Embedded 注释添加到字段或 getter(无论您通常使用哪个)。从这里您可以使用 @AttributeOverride 进一步调整列定义。
您可以尝试joda时间休眠。请参阅可持久化的可用类型。然后,您可以通过以下方式使用 joda Duration:
@Type(type="org.joda.time.contrib.hibernate.PersistentDuration")
private Duration startDateTime;
就我而言,我有一个 java.time.Duation 字段,它通过 javax.persistence.AttributeConverter 进行转换:
@Converter(autoApply = true)
public class DurationAttributeConverter implements AttributeConverter<Duration, Integer> {
@Override
public Integer convertToDatabaseColumn(Duration pX) {
if (pX == null) {
return null;
} else {
return (int) pX.toMinutes();
}
}
@Override
public Duration convertToEntityAttribute(Integer pY) {
if (pY == null) {
return null;
} else {
return Duration.ofMinutes(pY);
}
}
}
持续时间对象映射到数字列,该数字列存储持续时间(以分钟为单位)。