如何使用JPA从MySQL数据库中过滤行忽略MySQL中给定DateTime字段的时间部分?
例如,以下代码段计算数据库表中位于MySQL中DateTime
类型列中给出的两个日期之间的行数。
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Long>criteriaQuery=criteriaBuilder.createQuery(Long.class);
Root<Discount> root = criteriaQuery.from(entityManager.getMetamodel().entity(Discount.class));
criteriaQuery.select(criteriaBuilder.countDistinct(root));
DateTimeFormatter dateTimeFormatter=DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa");
DateTime firstDate = dateTimeFormatter.parseDateTime("01-Oct-2013 11:34:26 AM").withZone(DateTimeZone.UTC);
DateTime secondDate = dateTimeFormatter.parseDateTime("31-Oct-2013 09:22:23 PM").withZone(DateTimeZone.UTC);
criteriaQuery.where(criteriaBuilder.between(root.get(Discount_.discountStartDate), firstDate, secondDate));
Long rowCount = entityManager.createQuery(criteriaQuery).getSingleResult();
两个参数firstDate
和secondDate
将依次动态显示。
如何重写此查询,以便比较不包括要委派给MySQL的SQL查询中的时间部分。
实体discount_start_date
中的列Discount
指定如下。
@Column(name = "discount_start_date")
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime discountStartDate;
答案 0 :(得分:2)
好像你工作太辛苦了。
(a)显然,MySQL提供DATE()
函数来提取日期的日期部分 -
时间场。 (我是Postgres人,并且不了解MySQL。)您可以使用该函数调用作为查询的一部分。但是我猜测,如果你在执行SQL查询之前首先通过Java中的Joda-Time计算得到你的开始和停止时间会更快,如下所示。
(b)为什么不用简单的SQL查询,两个标准SELECT?
来做这个在伪代码中:
Find Discount records that go into effect from the moment this month starts up until the moment the next month starts.
使用Java和Joda-Time为您提供开始和时间停止值。
org.joda.time.DateTime startOfThisMonth = new org.joda.time.DateTime().dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
org.joda.time.DateTime startofNextMonth = startOfThisMonth.plusMonths( 1 ).dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
注意:上面的代码使用默认时区。您应该在构造函数中指定时区。
MySql似乎缺乏复杂的时区处理时区等。所以我想你会把那些时间划分的DateTime对象转换为UTC。
org.joda.time.DateTime startOfThisMonthInUtc = startOfThisMonth.toDateTime( org.joda.time.DateTimeZone.UTC );
org.joda.time.DateTime startofNextMonthInUtc = startofNextMonth.toDateTime( org.joda.time.DateTimeZone.UTC );
然后执行操作以获取MySQL的日期时间值。
然后形成一个看起来像这样的查询......(注意>=
与<
之间没有等号的使用。)
SELECT title_, amount_, start_date_
FROM discount_
WHERE discount_.start_datetime_ >= startOfThisMonthFromJodaTime
AND discount_.start_datetime_ < startOfNextMonthFromJodaTime
;
在处理日期和时间时,通常最好使用当天的第一时刻,一个月的第一天等,而不是尝试查找最后时刻或结束时间。因此,我的查询基于查找行的概念,这些行的值在我感兴趣的时间范围之后的时刻达到,但不包括。