过滤TIMESTAMP的TIME部分不起作用(JPA2,HIBERNATE)

时间:2013-12-19 08:02:27

标签: java sql hibernate jpa

我想按时间戳的时间部分进行过滤。 我将 JPA2 hibernate oracle 数据库一起使用。我必须编写一个JPA查询,它返回实体,“ std ”属性的TIME部分高于参数的TIME部分。 我无法更改数据库端,也无法使用本机查询。

例如,我想搜索标准时间大于12:01的所有实体。所以我把这个日期参数放在我的JPA查询中:2013-11-11T12:01:01,但没有任何反应,结果列表包含带有std参数的元素(11:00)2013-12-13T11:00:00。

我的查询如下:

Query q = em.createQuery( "SELECT t  FROM Foo t WHERE t.std >= :p_1 ");
q.setParameter("p_1", myDate, TemporalType.TIME);

我的日期是:2013-12-11T12:01:01 (如果我使用toString:Wed Dec 11 12:01:01 UTC 2013)

在Entity类中, std 属性如下所示:

private java.util.Date std;

@javax.persistence.Column(name = "STD", nullable = false, insertable = true, updatable = true)
@javax.persistence.Temporal(javax.persistence.TemporalType.TIMESTAMP)
public java.util.Date getStd()
{
    return std;
}

public void setStd(java.util.Date value)
{
    this.std = value;
}

我还尝试将entityClass中的propertys的注释更改为:

@javax.persistence.Temporal(javax.persistence.TemporalType.TIME)
public java.util.Date getStd()
{
    return std;
}

但它没有帮助。

在sql中,std属性是TIMESTAMP:

"STD" TIMESTAMP (6) NOT NULL ENABLE,

我必须在hibernate中使用JPA查询,本机查询不是一个选项。 有人可以解释为什么它不起作用,我该怎么做呢?

谢谢!

编辑:

例如,如果数据库中的std值如下:

2013-12-08T10:00:00 
2013-12-08T14:00:00 
2013-12-11T10:00:00 
2013-12-11T14:00:00 
2013-12-14T10:00:00 
2013-12-14T14:00:00 

我在查询中添加“2013-12-11T12:00:00”,我想找回所有实体,其中“ std ”更高时间,不管日期。在这个例子中,这些:

2013-12-08T14:00:00
2013-12-11T14:00:00 
2013-12-14T14:00:00 

如果我检查hibernate调试日志,我可以看到std被映射到org.hibernate.TimeType。

  

[org.hibernate.hql.internal.ast.tree.DotNode](http- / 127.0.0.1:8080-1)   getDataType():std - > org.hibernate.type.TimeType@f600d7a

     

[org.hibernate.hql.internal.ast.tree.FromReferenceNode]   (http- / 127.0.0.1:8080-1)已解决:t.std - > foo0_.STD

     

[org.hibernate.hql.internal.ast.tree.FromReferenceNode]   (http- / 127.0.0.1:8080-1)已解决:t - > foo0_.ID

2 个答案:

答案 0 :(得分:1)

您显然可以在Hibernate / HQL中使用(某些,至少)SQL函数。这包括CAST,并要求DB正确响应(即,TIME类型存在且可从TIMESTAMP转换)。 如果它有效,它可能会像这样工作:

Query q = em.createQuery( "SELECT t  FROM Foo t WHERE CAST(t.std as TIME) >= :p_1 ");

(请注意我没有支持db / Hibernate实例来测试它。也可能依赖于Hibernate的版本。)

请注意,这将忽略任何索引!这更多的是这样一个事实:你只是查询部分数据,而不是Hibernate部分的一些缺陷

答案 1 :(得分:0)

解决方案是:

Query q = em.createQuery( 
    "SELECT t FROM Foo t WHERE ( EXTRACT(HOUR FROM t.std) * 60 + EXTRACT(MINUTE FROM t.std) ) >= :p_1" 
    );

Calendar cal = Calendar.getInstance();
cal.setTime(myDate);

int minutes = cal.get(Calendar.HOUR_OF_DAY) * 60 + cal.get(Calendar.MINUTE);
q.setParameter("p_1", minutes);