我想使用Java8 DateTime API中的LocalDate
和LocalDateTime
,
当值为date
时,无法持久保留postgresql timestamp
和null
。
异常消息:
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
)。
答案 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类型,没有麻烦