查询从datetime字段返回一天的记录

时间:2014-02-07 18:21:37

标签: java spring hibernate spring-mvc jpa

在使用hibernate和jpa的spring mvc应用程序中,我有一个查询需要返回日期在指定日期内的所有记录。这一天最终来自yyyy-mm-dd格式的url参数,并存储在joda localdate对象中。按天搜索记录的实体将joda DateTime作为要搜索的属性的类型。底层MySQL数据库的日期信息存储在TimeStamp字段中。为了从localdate转换为datetime,我阅读the localdate api并尝试day.toDateTimeAtStartOfDay(),但这会使参数变得过窄。我需要在一天中的24小时内获得所有记录,而不仅仅是当天第一天的那些记录。如何构造查询以便它在指定的日期返回TimeStamp字段中的每条记录,包括指定日期内的所有时间?

以下是在jpa存储库中包含查询的方法:

@Override
public Collection<Encounter> findByDay(LocalDate day){
    System.out.println("@@@@@@@@@@@@@@@ made it into findByDay()");
    DateTime myDT = day.toDateTimeAtStartOfDay();
    Query query = this.em.createQuery("SELECT DISTINCT encounter FROM Encounter encounter WHERE encounter.dateTime LIKE :day");
    query.setParameter("day", myDT);
    return query.getResultList();       
}

以下是MySQL中基础数据表的sql:

CREATE TABLE IF NOT EXISTS encounters(
  id int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  patient_id int(11) UNSIGNED NOT NULL,
  office_id int(11) UNSIGNED NOT NULL,
  provider_id int(11) UNSIGNED NOT NULL,
  start_date TIMESTAMP,
  status varchar(50),
  FOREIGN KEY (patient_id) REFERENCES patients(id),
  FOREIGN KEY (office_id) REFERENCES facilityAddresses(id),
  FOREIGN KEY (provider_id) REFERENCES providers(id)
)engine=InnoDB;

以下是Encounter实体的相关部分:

@Entity
@Table(name = "encounters")
public class Encounter extends BaseEntity{

    @Column(name="start_date")
    private DateTime dateTime;

    //other mappings of columns to properties

    // getters and setters

}  

编辑:

以下是我根据Affe的建议测试的内容:

@Override
public Collection<Encounter> findByDay(LocalDate day){
    System.out.println("kkkkkkkkkkkkkkkkkkkkkk inside repository.findByDay()  ");
    DateTime startDay = day.toDateTimeAtStartOfDay();
    DateTime startNextDay = startDay.plusDays(1);
    System.out.println("startDay is: "+startDay);
    System.out.println("startNextDay is: "+startNextDay);
    Query query = this.em.createQuery(
        "SELECT DISTINCT encounter " +
        "FROM Encounter encounter " +
        "WHERE encounter.dateTime >= :startDay and encounter.dateTime < :startNextDay");
    query.setParameter("startDay", startDay);
    query.setParameter("startNextDay", startNextDay);
    Collection<Encounter> myresult = query.getResultList();
    Object[] something = myresult.toArray();
    System.out.println("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv num results is: "+myresult.size());
    for(int i=0;i<something.length;i++){
        System.out.println("nnnnnnnnnnnnnnnnnnnnnnnnn "+something[i].toString());
    }
    return myresult;
}

以下是将测试数据插入数据库的SQL:

INSERT IGNORE INTO encounters VALUES (1, 5, 2, 1, '2013-11-30 09:00:00','Active');
INSERT IGNORE INTO encounters VALUES (2, 4, 1, 2, '2013-12-15 10:00:00','Inactive');
INSERT IGNORE INTO encounters VALUES (3, 3, 4, 3, '2014-1-10 11:00:00','Active');
INSERT IGNORE INTO encounters VALUES (4, 2, 3, 4, '2014-1-13 12:00:00','Inactive');
INSERT IGNORE INTO encounters VALUES (5, 1, 1, 3, '2014-1-12 13:00:00','Inactive');

当我选择2014-1-102014-1-132014-1-12或其他插入的日期作为参数时,上面的system.out.println()打印出的结果数为零,因此for循环从不运行。查询应返回每个日期的结果。

例如,当我选择2014-1-10时,会在eclipse控制台中输出以下内容:

kkkkkkkkkkkkkkkkkkkkkk inside repository.findByDay()  
startDay is: 2014-01-10T00:00:00.000-08:00
startNextDay is: 2014-01-11T00:00:00.000-08:00
Hibernate: select distinct encounter0_.id as id1_10_, encounter0_.start_date as start2_10_, encounter0_.office_id as office4_10_, encounter0_.patient_id as patient5_10_, encounter0_.status as status3_10_ from encounters encounter0_ where encounter0_.start_date>=? and encounter0_.start_date<?
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv num results is: 0
number of encounters is: 0
aaaa hours of day, mins of hour for block: 8, 0
aaaa hours of day, mins of hour for block: 9, 0
aaaa hours of day, mins of hour for block: 10, 0
aaaa hours of day, mins of hour for block: 11, 0
aaaa hours of day, mins of hour for block: 12, 0
aaaa hours of day, mins of hour for block: 13, 0
aaaa hours of day, mins of hour for block: 14, 0
aaaa hours of day, mins of hour for block: 15, 0
aaaa hours of day, mins of hour for block: 16, 0

datetime输出的System.out.println()格式是否与问题有关?我做错了什么?

3 个答案:

答案 0 :(得分:2)

问题的解决方案非常简单。我只需要将@Type注释添加到Encounter实体的dateTime字段,如下所示:

@Column(name="start_date")
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime dateTime;

将这一行代码添加到实体后,我的原始jpa / sql代码正常工作。

答案 1 :(得分:1)

您需要搜索特定日期的所有时间戳范围。将时间戳作为数据库中的日期处理的功能是特定于数据库的,不能通过JPA API获得。 (除非你根据日期值建立了功能索引,否则通常都是个坏主意。)

@Override
public Collection<Encounter> findByDay(LocalDate day){
    DateTime startDay = day.toDateTimeAtStartOfDay();
    DateTime startNextDay = startDay.plusDays(1);
    Query query = this.em.createQuery(
        "SELECT DISTINCT encounter " +
        "FROM Encounter encounter " +
        "WHERE encounter.dateTime >= :startDay and encounter.dateTime < :startNextDay");
    query.setParameter("startDay", startDay);
    query.setParameter("startNextDay", startNextDay);
    return query.getResultList();       
}

答案 2 :(得分:0)

我的问题是日期格式

您可以在yyyy-MM-dd HH:mm:ss (即2013-11-30 09:00:00)格式的数据库中存储日期 并且你是yyyy-MM-dd'T'HH:mm:ss (即2014-01-10T00:00:00.000-08:00)格式的passig日期来查询

首先,您必须将给定格式的LocalDate转换为

LocalDate localDate = new LocalDate(2010, 9, 14);
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
String startDay = formatter.print(localDate);

然后你必须将它设置为查询参数

Query query = this.em.createQuery(
    "SELECT DISTINCT encounter " +
    "FROM Encounter encounter " +
    "WHERE encounter.dateTime = "+ startDay +"");

希望这能解决您的问题!