在使用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-10
,2014-1-13
,2014-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()
格式是否与问题有关?我做错了什么?
答案 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 +"");
希望这能解决您的问题!