JPA和Hibernate:仅比较时间戳的时间部分

时间:2012-11-01 16:41:00

标签: java hibernate jpa jpql

我正在通过JPA使用Hibernate,我需要按照Date属性的时间部分过滤记录。

public class Foo {
    Date getDateTime() {
        // Returns a date and time value.
    }
}

Time startTime = ...;
Time endTime = ...;

TypedQuery<Foo> query = entityManager.createQuery("SELECT foo FROM Foo foo where :startTime <= foo.dateTime AND foo.dateTime <= :endTime", Foo.class);
query.setParameter("startTime", startTime);
query.setParameter("endTime ", endTime);

当然这不起作用,因为您无法直接比较DateTime。如果这是一个SQL查询,那么我会使用一些特定于DBMS的日期函数来比较它们,但是如何比较JPA中的日期和时间?

3 个答案:

答案 0 :(得分:3)

如果您使用的是JPA,则可以使用 @Temporal(TemporalType.TIME) 它将仅返回TIMESTAMP的Time部分。 喜欢: @Temporal(TemporalType.TIME) 日期getDateTime()

答案 1 :(得分:2)

为什么不使用Native Query,然后利用您熟悉的数据库特定功能。获得Native Query后,您可以将java.sql.Time个对象转换为long并执行它。

EntityManager API Documentation

例如,如果您使用的是Oracle。

            long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
    long startTimeMillis = (startTime.getTime() % MILLIS_PER_DAY)/1000;
    long stopTimeMillis = (endTime.getTime() % MILLIS_PER_DAY)/1000;
    entityManager
            .createNativeQuery(
                    "select * from foo where to_number(to_char(date_time, 'sssss')) between ?1 and ?2", Foo.class)
            .setParameter(1, startTimeMillis)
            .setParameter(2, stopTimeMillis).getResultList();

实际查询将根据您的数据库风格而有所不同,但是创建NativeQuery应该允许您利用特定于数据库的基础供应商功能。

解决此挑战的另一种方法是创建一个视图,其中包含一个包含日期数据类型的列的时间部分的列。这将允许您以代码中透明的方式利用底层数据库技术。设置此列后,您将在查询中建立正确的where子句。

答案 2 :(得分:1)

没有任何简单或标准化的方法可以仅使用JPA2与现有日期时间/时间戳列的时间(或日期)组件进行比较。选项:

  1. 使用原生查询。如果您需要秒精度(而不是毫秒),kmb385's answer可以正常工作。我认为更常见的本机SQL方法是使用CAST或EXTRACT来仅与时间组件进行比较。

  2. 将另一列添加到仅包含日期时间的时间组件的表/视图中,并使用该列进行比较。您可能还会使用@Temporal(TemporalType.TIME)注释向Foo添加另一个字段。