Java 在条件查询where子句中使用日期

Java 在条件查询where子句中使用日期,java,hibernate,h2,criteria-api,Java,Hibernate,H2,Criteria Api,我有一个带有java.util.Date字段的实体,该字段存储为TemporalType.Date。当将带有小时、分钟或秒的java.util.Date传递给条件查询的where子句时,我似乎无法从数据库中获得匹配项 该设置是Spring中带有Hibernate的嵌入式H2数据库。我尝试过使用PostgreSQL而不是H2,而且效果很好。我还尝试在PostgreSQL模式下设置H2,但它没有改变任何东西 给定实体 @Entity public class SomeEntity { @I

我有一个带有
java.util.Date
字段的实体,该字段存储为
TemporalType.Date
。当将带有小时、分钟或秒的
java.util.Date
传递给条件查询的where子句时,我似乎无法从数据库中获得匹配项

该设置是Spring中带有Hibernate的嵌入式H2数据库。我尝试过使用PostgreSQL而不是H2,而且效果很好。我还尝试在PostgreSQL模式下设置H2,但它没有改变任何东西

给定实体

@Entity
public class SomeEntity {

    @Id
    private int id;

    @Temporal(TemporalType.DATE)
    private java.util.Date aDate;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Date getDate() {
        return aDate;
    }

    public void setDate(Date aDate) {
        this.aDate = aDate;
    }
}
以下查询仅在参数的小时、分钟和秒设置为0时返回匹配

public List<SomeEntity> someQueryOnDate(Date date) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<SomeEntity> query = cb.createQuery(SomeEntity.class);

    Root<SomeEntity> root = query.from(SomeEntity.class);
    Predicate dateEquals = cb.equal(root.get(SomeEntity_.date), date);
    query.where(dateEquals);

    // This list is always empty if the date in the predicate has a time part
    return em.createQuery(query).getResultList(); 
}
公共列表someQueryOnDate(日期){
CriteriaBuilder cb=em.getCriteriaBuilder();
CriteriaQuery=cb.createQuery(SomeEntity.class);
Root=query.from(SomeEntity.class);
谓词dateEquals=cb.equal(root.get(SomeEntity_uu.date),date);
查询。其中(dateEquals);
//如果谓词中的日期有时间部分,则此列表始终为空
返回em.createQuery(query.getResultList();
}
下面是一个完整的例子。测试在最后一个断言中失败,我使用设置了小时、分钟和秒的日期查询数据库

@Test
public void testDateEquals() throws ParseException {
    Date dateWithoutTime = new SimpleDateFormat("yyyy-MM-dd").parse("2014-07-03");
    Date dateWithTime    = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2014-07-03 09:45:01");

    createEntity(dateWithoutTime);

    List<SomeEntity> entitiesMatchingDateWithTime    = listAllEntitiesWithDate(dateWithTime);
    List<SomeEntity> entitiesMatchingDateWithoutTime = listAllEntitiesWithDate(dateWithoutTime);

    Assert.assertFalse("No entities matched the date without time", entitiesMatchingDateWithoutTime.isEmpty());
    Assert.assertFalse("No entities matched the date with time"   , entitiesMatchingDateWithTime.isEmpty());
}

private void createEntity(Date d) {
    SomeEntity entity = new SomeEntity();
    entity.setDate(d);
    em.persist(entity);

    // For good measure
    em.flush();
    em.clear();
}

private List<SomeEntity> listAllEntitiesWithDate(Date date) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<SomeEntity> query = cb.createQuery(SomeEntity.class);

    Root<SomeEntity> root = query.from(SomeEntity.class);
    Predicate dateEquals = cb.equal(root.get(SomeEntity_.date), date);
    query.where(dateEquals);

    return em.createQuery(query).getResultList();
}
@测试
public void testDateEquals()引发ParseException{
Date dateWithoutTime=新的简化格式(“yyyy-MM-dd”)。解析(“2014-07-03”);
Date dateWithTime=新的简化格式(“yyyy-MM-dd HH:MM:ss”)。解析(“2014-07-03 09:45:01”);
createEntity(dateWithoutTime);
List EntityMatchingDateWithTime=ListAllEntityWithDate(dateWithTime);
List Entities Matching Date Without Time=ListalEntities Without Date(Date Without Time);
Assert.assertFalse(“没有实体匹配没有时间的日期”,entitiesMatchingDateWithoutTime.isEmpty());
Assert.assertFalse(“没有实体将日期与时间匹配”,entitiesMatchingDateWithTime.isEmpty());
}
私有实体(日期d){
SomeEntity=新的SomeEntity();
实体。设定日期(d);
em.persist(实体);
//适当地
em.flush();
em.clear();
}
私有列表列表具有日期的实体(日期){
CriteriaBuilder cb=em.getCriteriaBuilder();
CriteriaQuery=cb.createQuery(SomeEntity.class);
Root=query.from(SomeEntity.class);
谓词dateEquals=cb.equal(root.get(SomeEntity_uu.date),date);
查询。其中(dateEquals);
返回em.createQuery(query.getResultList();
}

这里可能提供了解决方案:


您可以使用
限制
来比较日期。

谢谢您的回答!我来看看限制。但是,因为我知道它在PostgreSQL中工作而不改变查询,所以我更喜欢一种配置H2的方法,以不同的方式处理日期。假设这是可能的:)