2013-11-25 57 views
0

如何使用JPA忽略MySQL中給定DateTime字段的時間部分,從MySQL數據庫中過濾行?從基於DateTime列的MySQL中獲取記錄忽略使用JPA和Joda-Time的時間部分

例如,以下代碼段計算數據庫表中位於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中的列discount_start_date被指定如下。

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

是否真的需要委託給MySQL?如果不是,你可以在'DateTime.withMillisOfDay(0)'和'DateTime.withMillisOfDay(0).plusDays(1).plusMillis(-1)' – samlewis

+0

@samlewis之間使用,比['withMillisOfDay'](http:// joda -time.sourceforge.net/apidocs/org/joda/time/DateTime。html#withMillisOfDay(int))會[[withTimeAtStartOfDay]](http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html#withTimeAtStartOfDay())。不是每個時區都有午夜,所以最好避免以午夜爲導向的數學。 「withTimeAtStartOfDay」已添加到[Joda-Time](http://www.joda.org/joda-time/)以處理夏令時或其他可能會改變日期的問題。 –

+0

'withMillisOfDay(0)'和'withTimeAtStartOfDay()'都會生成'[2013-10-02 05:30.90.0,2013-11-01 05:29:59.999]''的日期。其實,時間部分應該完全避免。這可能嗎?它應該對應於這個MySQL查詢 - ''選擇count(*)作爲cnt從折扣'2013-10-02'和'2013-11-01'之間的日期(discount_start_date)。 – Tiny

回答

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和喬達時間,讓您開始&停止值。

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 
; 

當日期和時間的工作,它通常是更好地與第一工作一天的時刻,一個月的第一天的第一時刻等,而不是試圖找出最後一刻或結束時間。因此,我的查詢是基於查找行的值的想法,這些行的值在我感興趣的時間範圍之後的某個時間點上升,但不包括在內。

相關問題