基于DateTime列从MySQL获取记录,忽略使用JPA和Joda-Time的时间部分

时间:2013-11-25 22:46:29

标签: mysql datetime jpa criteria jodatime

如何使用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();

两个参数firstDatesecondDate将依次动态显示。

如何重写此查询,以便比较不包括要委派给MySQL的SQL查询中的时间部分。

实体discount_start_date中的列Discount指定如下。

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

1 个答案:

答案 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
;

在处理日期和时间时,通常最好使用当天的第一时刻,一个月的第一天等,而不是尝试查找最后时刻或结束时间。因此,我的查询基于查找行的概念,这些行的值在我感兴趣的时间范围之后的时刻达到,但不包括。