java.time and JPA



类作为java.timeLocalDateTime类是基于价值的类。如果我有一个将这样对象作为字段的实体,我会遇到以下"问题":基于价值的类不应序列化。但是,JPA实体必须实现可序列化的接口。该悖论的解决方案是什么?有人不应该将LocalDateTime用作JPA实体的字段吗?使用日期?这将是不满意的。

这个问题是声纳规则squid:S3437,因此项目中有很多错误,因为我们从日期更改为LocalDateTime ...

由于基于价值的类用法而导致的非兼容解决方案:

@Entity
public class MyEntity implements Serializable{
    @Column
    private String id; // This is fine
    @Column
    private LocalDateTime updated; // This is not ok, as LocalDateTime is a value based class
    @Column
    private Date created; // This however is fine..
}

我的答案似乎很直接和毫无价值,但更多的是将事情聚在一起并进行总结。

首先,这个问题没有"金色子弹"解决方案。肯定必须更改一些东西,我看到3个选项或3个替代方案:

  1. 删除Serializable接口。将Serializable放在所有实体上不是"好习惯"。仅当您要将其实例用作分离对象时才需要:JPA实体应实现可序列化接口?。

  2. 使用时间戳类型而不是LocalDateTime。在我看来,这是等效的:

https://github.com/javaee/jpa-pec/issues/63

即时,localdateTime,oftsetDateTime和ZoneddateTime Map as 默认情况下时间戳值。您可以标记其中之一 带有@Temporal的类型来指定持久的不同策略 该属性。

  1. 如果两个第一个选项都不适合您,那么(我很确定,您知道该怎么做) - 压制此警告@SuppressWarnings("squid:S3437")

我不太了解您的DB从JPA接受什么。当我与Postgres打交道时,我会使用自定义的转换器:

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.sql.Timestamp;
import java.time.LocalDateTime;
@Converter(autoApply = true)
public class LocalDateTimePersistenceConverter implements AttributeConverter<LocalDateTime, Timestamp> {
    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime locDateTime) {
        return (locDateTime == null ? null : Timestamp.valueOf(locDateTime));
    }
    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
        return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime());
    }
}

我这样使用:

@Column(name = "create_date")
@Convert(converter = LocalDateTimePersistenceConverter.class)
private LocalDateTime createDate;

您看到,在这里,我将LocalDateTime转换为Timestamp(由Postgres接受)和返回。

最新更新