简体   繁体   English

java.time和JPA

[英]java.time and JPA

Classes as LocalDateTime from the package java.time are value based classes . 来自包java.time LocalDateTime类是基于值的类 If I have an entity using such an object as a field I run into the following "problem": Value based classes shouldn't be serialized. 如果我有一个实体使用这样的对象作为字段,我会遇到以下“问题”:不应序列化基于值的类。 However, the JPA entity has to implement the interface Serializable. 但是,JPA实体必须实现Serializable接口。 What is the solution for that paradox? 这个悖论的解决方案是什么? Shouldn't someone use LocalDateTime as a field of an JPA entity? 不应该有人使用LocalDateTime作为JPA实体的字段吗? Use Date instead? 使用日期代替? This would be unsatisfying. 这将是不满意的。

This problem is a Sonar rule squid:S3437 and therefore there are a lot of bugs in the project, since we changed from Date to LocalDateTime ... 这个问题是一个声纳规则squid:S3437 ,因此项目中有很多错误,因为我们从Date更改为LocalDateTime ...

Non compliant solution due to value based class usage: 基于价值的课程使用导致的不合规解决方案:

@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..
}

I don't quite understand what you DB accepts from jpa. 我不太明白你的数据库从jpa接受了什么。 When I deal with Postgres, I use a customized converter: 当我处理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());
    }
}

And I use it this way: 我用这种方式使用它:

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

You see, here I convert LocalDateTime to Timestamp (accepted by postgres) and back. 你看,在这里我将LocalDateTime转换为Timestamp(由postgres接受)并返回。

My answer could seem quite direct and valueless, but it is more for getting things together and to summarise. 我的回答看起来很直接,毫无价值,但更多的是将事情放在一起并总结。

First thing, it that there is no "golden bullet" solution of this problem. 首先,它没有这个问题的“金子弹”解决方案。 Something definitely has to be changed and I see 3 options or 3 alternatives: 肯定要改变一些东西,我看到3种选择或3种选择:

  1. Remove Serializable interface. 删除Serializable接口。 It is not a "good practice" to put Serializable on all entities. Serializable放在所有实体上并不是一个“好习惯”。 It is needed only if you are going to use instances of it as detached objects: When and why JPA entities should implement Serializable interface? 只有当您要将它的实例用作分离对象时才需要它: JPA实体何时以及为何应该实现Serializable接口? .

  2. Use Timestamp type instead of LocalDateTime. 使用Timestamp类型而不是LocalDateTime。 It seems to me that it is equivalent: 在我看来它是等价的:

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

Instant, LocalDateTime, OffsetDateTime, and ZonedDateTime map as timestamp values by default. 默认情况下,Instant,LocalDateTime,OffsetDateTime和ZonedDateTime映射为时间戳值。 You may mark a property of one of these types with @TeMPOraL to specify a different strategy for persisting that property. 您可以使用@TeMPOraL标记其中一种类型的属性,以指定用于持久保存该属性的不同策略。

  1. If both first options do not work for you, then (I am pretty sure, you know what to do) - suppress this warning @SuppressWarnings("squid:S3437") . 如果两个第一选项都不适合你,那么(我很确定,你知道该怎么做) - 抑制这个警告@SuppressWarnings("squid:S3437")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM