java.time和JPA

时间:2017-12-18 09:22:21

标签: java jpa java-8 sonarqube java.time.instant

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

这个问题是一个声纳规则squid:S3437,因此项目中存在很多错误,因为我们从Date更改为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..
}

2 个答案:

答案 0 :(得分:2)

我的回答看起来非常直接且毫无价值,但更重要的是将事情放在一起并进行总结。

首先,它没有"金色的子弹"解决这个问题。肯定有些东西需要改变,我看到3种选择或3种选择:

  1. 删除Serializable界面。这不是一个好的做法"将Serializable放在所有实体上。仅当您要将其实例用作分离对象时才需要它:When and why JPA entities should implement Serializable interface?

  2. 使用Timestamp类型而不是LocalDateTime。在我看来它是等价的:

  3. https://github.com/javaee/jpa-spec/issues/63

      

    Instant,LocalDateTime,OffsetDateTime和ZonedDateTime map as   默认情况下,时间戳值。您可以标记其中一个的财产   使用@TeMPOraL指定不同的持久策略   该财产。

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

答案 1 :(得分:1)

我不太明白你的数据库从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接受)并返回。