2017-05-30 123 views
1

我有一個java.lang.String,其中包含一個精度爲微秒的時間戳。 我想通過JPA比較jpa中的時間戳列而不會丟失微秒

(在query.setParameter方法參數),以比較這時間戳與在Oracle數據庫後端一個TIMESTAMP

查詢:

select CUSTOMER_NAME from CUSTOMER where REG_TIME < timestamp_which_i_want_to_pass; 

當我在答覆稱爲給定在stackoverflow_link我知道要與DB時間戳進行比較的javatype應該是java.util.Datejava.util.Calendar

我的問題是,如果我將timeStamp(字符串)轉換爲Date/Calendar,我將失去微秒。但我需要準確的比較。

如何實現這種比較而不會丟失微秒?

回答

0

由於Nor java.util.Date和java.util.Calendar的精確度都是微秒級,所以請不要將它們用作參數!

使用具有納秒精度的java.sql.Timestamp。在這種情況下,小心地設置納米領域上的時間戳 (java.sql.Timestamp way of storing NanoSeconds

我創建了一個簡單的場景來進行測試:

CREATE TABLE precisetimes(id NUMBER(2), precisetime TIMESTAMP(6)); 
insert into precisetimes values(1, TO_TIMESTAMP('2017-05-31 12:12:12.123456','YYYY-MM-DD HH:MI:SS.FF')); 
insert into precisetimes values(2, TO_TIMESTAMP('2017-05-31 12:12:12.12','YYYY-MM-DD HH:MI:SS.FF')); 
insert into precisetimes values(3, TO_TIMESTAMP('2017-05-31 12:12:12.123457','YYYY-MM-DD HH:MI:SS.FF')); 
commit; 

select id,TO_CHAR(precisetime, 'YYYY-MM-DD HH:MI:SS.FF') ptime from precisetimes; 

選擇所有:

 ID PTIME      
---------- ----------------------------- 
     1 2017-05-31 12:12:12.123456 
     2 2017-05-31 12:12:12.120000 
     3 2017-05-31 12:12:12.123457 

在此準備後,以下代碼:

TypedQuery<Precisetimes> q = entityManager.createQuery(
     "select p from Precisetimes p where p.precisetime < :param", 
     Precisetimes.class); 
Timestamp ts; 
ts = Timestamp.valueOf("2017-05-31 12:12:12.123456"); 
q.setParameter("param", ts, TemporalType.TIMESTAMP); 
System.out.println("result: " + q.getResultList()); 
ts = Timestamp.valueOf("2017-05-31 12:12:12.123457"); 
q.setParameter("param", ts, TemporalType.TIMESTAMP); 
System.out.println("result: " + q.getResultList()); 
ts = Timestamp.valueOf("2017-05-31 12:12:12.123458"); 
q.setParameter("param", ts, TemporalType.TIMESTAMP); 
System.out.println("result: " + q.getResultList()); 

有這樣的結果:

result: [id: 2, precisetime: 2017-05-31 12:12:12.12] 
result: [id: 1, precisetime: 2017-05-31 12:12:12.123456, id: 2, precisetime: 2017-05-31 12:12:12.12] 
result: [id: 1, precisetime: 2017-05-31 12:12:12.123456, id: 2, precisetime: 2017-05-31 12:12:12.12, id: 3, precisetime: 2017-05-31 12:12:12.123457] 

我想這是你需要什麼?我上傳這裏的測試例子:http://peter.risko.hu/java_incubator/jpa_hibernate_oracle_precisetimestamp.zip

注意,有一個倒過來,通過TO_CHAR函數甲骨文時間戳轉換爲字符串在Select語句:

select id,TO_CHAR(precisetime, 'YYYY-MM-DD HH:MI:SS.FF') ptime from precisetimes 
    where TO_CHAR(precisetime, 'YYYY-MM-DD HH:MI:SS.FF') > '2017-05-31 12:12:12.123457'; 

結果:

 ID PTIME      
---------- ----------------------------- 
     1 2017-05-31 12:12:12.123456 
     2 2017-05-31 12:12:12.120000 

但爲此,您必須使用JPA的Criteria API或本機查詢,因爲JPQL不支持本機函數。在這種情況下,請注意在數據庫端和Java端使用相同的格式。

+1

任何想法如何翻譯JPA中的TO_CHAR? –

+0

Alagammal,對不起,我剛剛意識到您使用JPQL。您必須使用JPA的Criteria API或TO_CHAR的本機查詢。 JPQL不支持本機功能。 – riskop

0

有幾個可能的方式:

1)包含在DB到long微秒時間戳更改值類型,然後將您TIMESTAMPlong以及添加有微秒填充000。例如:

long timestampWithoutMicroSeconds = 1496218445; 
long timestampWithMicroseconds = timestampWithoutMicroSeconds * 1000; 

然後,只需使用您的查詢來選擇正確的結果。

2)根據你的數據庫你可以使用contains像運營商。這意味着你要搜索參數(TIMESTAMP)轉換爲String,並使用這樣的查詢:

WHERE `column` LIKE '%part%' 

這意味着你會選擇哪裏column含有「部分」的所有記錄。例如:

|username|time_with_micro | 
|+------+|+------------------| 
| test | 1496218445123  | 

Select * from table where time_with_micro like %1496218445% 

它會選擇您的值。

此外,使用這種方法,你必須使用%符號,因爲它定義了未知部分。在您的任務中,您需要選擇您的時間開始的所有記錄,以避免碰撞。然後它會完成你正在尋找的東西,所有記錄時間更長(>)然後你正在尋找將被選中。

+0

1.數據庫顏色不能修改,因爲它是現有的2.我想要選擇其中TImestamp列包含比我想要傳遞的值更小的值的記錄。 (不確定如果like可以準確地獲取結果) –

+0

您可以編寫一個腳本,在'String'列中添加一個'long'類型和值的附加列,然後刪除該'String'列。 –

+0

在不更改列類型的情況下,不能使用帶'String'類型的< >運算符。只包含(以/開頭)或等於。 –

0

你可以用下面的步驟參數類型轉換:

String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(param); 
Timestamp time = Timestamp.valueOf(date); 

我希望這有助於。

+0

setParameter(String name,java.util.Date value,TemporalType temporalType)' setParameter(String name,java.util.Calendar value,TemporalType temporalType)' –

+0

1.因此,我猜想轉換後的TimeStamp不能用於setParamter 1 。方法 –

+0

2.我想微秒(6位)不是毫秒 –