当LocalDate为null时,持久化到postgresql的日期的Java8 LocalDate JPA2.2失败

时间:2018-02-07 07:40:37

标签: java postgresql jpa java-8

我想使用Java8 DateTime API中的LocalDateLocalDateTime, 当值为date时,无法持久保留postgresql timestampnull

异常消息:

Internal Exception: org.postgresql.util.PSQLException: ERROR: column "some_date" is of type date but expression is of type character varying
hint: You will need to rewrite or cast the expression.
position: 61
Error Code: 0
Call: INSERT INTO TEST (ID, some_date, some_timestamp) VALUES (?, ?, ?)
bind => [0, null, null]
Query: InsertObjectQuery(mypackage.TestEntity@38c9e0d6)

postgresql驱动程序和JPA2.2的maven依赖项:

<dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.2.0</version>
</dependency>
<dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>org.eclipse.persistence.jpa</artifactId>
        <version>2.7.1</version>
</dependency>
<dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>javax.persistence</artifactId>
        <version>2.2.0</version>
</dependency>

postgresql10.1上的test表(没有not null约束):

create table test (id serial, some_date date, some_timestamp timestamp);

我的TestEntity课程:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.time.LocalDate;
import java.time.LocalDateTime;

@Entity(name="test")
public class TestEntity {

    @Id
    private int id;

    @Column(name="some_date")
    private LocalDate someDate;

    @Column(name="some_timestamp")
    private LocalDateTime someTimestamp;

   //simple getters and setters here.
}

我的testMethod

public void testMethod() {
    TestEntity testEntity = new TestEntity();
    // IF I set both someDate and someTimestamp via setters,
    //I don't get any exceptions (table data will be added successfully)
    em.getTransaction().begin();
    em.persist(testEntity);
    em.getTransaction().commit(); //this is where the exception occurs.
}

我错过了什么?有没有解决方法呢?

修改 几个月后,我意识到这个问题不再发生了。可能是因为我将服务器实现从Grizzly切换到Payara5.181。 事后不需要自定义转换器(即使值为null)。

3 个答案:

答案 0 :(得分:1)

您可以为LocalDate属性(JPA 2.1和+)创建一个转换器,如下所示:

@Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> {

    @Override
    public Date convertToDatabaseColumn(LocalDate locDate) {
        return (locDate == null ? null : Date.valueOf(locDate));
    }

    @Override
    public LocalDate convertToEntityAttribute(Date sqlDate) {
        return (sqlDate == null ? null : sqlDate.toLocalDate());
    }
}

并在LocalDate属性中使用转换器:

@Entity(name="test")
public class TestEntity {

    @Id
    private int id;

    @Converter(converter=LocalDateAttributeConverter.class)
    @Column(name="some_date")
    private LocalDate someDate;

    ...

   //simple getters and setters here.
}

答案 1 :(得分:1)

这似乎是eclipselink https://bugs.eclipse.org/bugs/show_bug.cgi?id=535431中的错误。如果LocalDate值为null,则没有适当的JDBC类型映射,并且默认情况下将其设置为VARCHAR,并且驱动程序引发异常。

作为一种解决方法,我们使用所需的映射创建了PatchedPostgreSQLPlatform并将其设置为eclipselink.target-database属性的值。

docker -v

答案 2 :(得分:0)

使用@Temporal(TemporalType.DATE)注释someDate,使用@Temporal(TemporalType.TIMESTAMP)注释someTimestamp ...只保存sql类型,没有麻烦