JPA中的Java 8日期时间API

14

如何最佳集成 Java 8 日期时间 API 到 JPA?

我已添加转换器:

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

    @Override
    public Date convertToDatabaseColumn(LocalDate localDate) {
        return Date.valueOf(localDate);
    }

    @Override
    public LocalDate convertToEntityAttribute(Date date) {
        return date.toLocalDate();
    }
}

@Converter(autoApply = true)
public class LocalDateTimePersistenceConverter implements AttributeConverter<LocalDateTime, Timestamp> {
    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime entityValue) {
        return Timestamp.valueOf(entityValue);
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp databaseValue) {
        return databaseValue.toLocalDateTime();
    }
}

一切看起来都很好,但是我该如何使用JPQL进行查询?我正在使用Spring JPARepository,我的目标是选择所有日期与给定日期相同的实体,唯一的区别是它以LocalDateTime格式保存在实体中。

因此:

public class Entity  {

    private LocalDateTime dateTime;

    ...
}

而且:

@Query("select case when (count(e) > 0) then true else false end from Entity e where e.dateTime = :date")
public boolean check(@Param("date") LocalDate date);

执行时只是抛出异常,这是正确的。

Caused by: java.lang.IllegalArgumentException: Parameter value [2014-01-01] did not match expected type [java.time.LocalDateTime (n/a)]

我尝试了很多方法,但似乎没有一种方法起作用,这可能吗?


你的领域类型是LocalDateTime。你的参数类型是LocalDate。它应该是LocalDateTime类型。当执行查询时会发生什么? - JB Nizet
是的,我明白了,我需要保存日期时间,但按日期查询。 - sandris
1
那么为什么不使用 date.atStartOfDay() 将您的 LocalDate 转换为 LocalDateTime?错误消息明确告诉您参数类型不正确,应该是 LocalDateTime 类型。 - JB Nizet
“最佳方式”取决于您的JPA实现。我使用的JPA实现(DataNucleus JPA)允许它直接工作,无需特殊代码。你在用什么? - user3973283
如果某些内容以时间戳(包含时间)的形式存储在数据库中,则需要使用数据存储函数来提取天、月、年并将其与输入值进行比较。 - Neil Stockton
显示剩余2条评论
3个回答

7
Hibernate有一个扩展库,我相信它叫做hibernate-java8,原生支持许多时间类型。在编写转换器之前,您应该使用它。
在Hibernate 5.2中,您将不需要此额外的库,因为它已成为核心的一部分。

+1 提到了 Hibernate 5.2 默认具备此功能。我正在使用 JPA2.1 和 Hibernate-core 5.2,没有遇到这个问题。 - The Coder

1
要查询时间字段,您应该在时间字段中使用@Temporal注释,在persistence.xml中添加转换器,并确保您在转换器中使用java.sql.Date、java.sql.Time或java.sql.Timestamp。(有时我从错误的包中导入)
例如,以下内容适用于我:
@Temporal(TemporalType.TIMESTAMP)
@Convert(converter = InstantPersistenceConverter.class)
private Instant StartInstant;
@Temporal(TemporalType.TIME)
@Convert(converter = LocalTimePersistenceConverter.class)
private LocalTime StartTime;

和我的即时转换器:
@Converter(autoApply = true)
public class InstantPersistenceConverter implements   AttributeConverter <Instant,java.sql.Timestamp>{
@Override
public java.sql.Timestamp convertToDatabaseColumn(Instant entityValue) {
    return java.sql.Timestamp.from(entityValue);
}

@Override
public Instant convertToEntityAttribute(java.sql.Timestamp databaseValue) {
    return databaseValue.toInstant();
}

}


0
你在位于“class”元素中的persistence.xml中添加了LocalDatePersistenceConverter和LocalDateTimePersistenceConverter吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接