2017-03-03 57 views
0

我試圖讓查詢看起來像:如何使用JPA調用SQL本機函數,需要不斷的參數?

select count(*) from somewhere group by DATEDIFF(week, '2010-01-01', creation_date); 

我的問題是關於函數調用。我使用JPA的CriteriaBuilder(CB)與Hibernate下方(根是我的某處):

cb.function("DATEDIFF", Integer.class, cb.literal("week"), cb.literal('2010-01-01'), root.<Date>get("creationDate") 

生成的SQL是:

select count(*) from somewhere group by DATEDIFF(?, ?, creation_date); 
- param1: 'week' 
- param2: '2010-01-01' 

這是行不通的,因爲第一個函數參數應該是一個常數不一個 」?」。

我怎樣才能給這個常量參數注入像它(沒有引號,而不是參數)?

感謝

我在這種情況下,對象是一樣的東西:

@Entity 
public class Somewhere { 
    @Id 
    private Long id; 

    @Column(nullable = false) 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date creationDate; 

    // Getters and setters 
} 
+0

可以嘗試cb.parameter(String.class,「周」),而不是cb.literal(「周」)和告訴我發生了什麼? –

+0

已經嘗試過,它只是抱怨參數周沒有被設置。當我設置它時,它就變成了它正在使用的字面值(查詢中的問號,後面有一個參數集)。 – Dush

+1

通過JPA標準API設置文字是不可能的,這些值將始終作爲參數插入。你可以通過實現'SQLFunction'接口創建你自己的'DATEDIFF'函數, day_diff,month_diff等固定了第一個參數。 –

回答

3

基於基督教的評論,其實解決辦法是實現非常簡單。

Sql Server的方言的新功能的 'weekdiff':

import org.hibernate.dialect.SQLServerDialect; 
import org.hibernate.dialect.function.SQLFunctionTemplate; 
import org.hibernate.type.StandardBasicTypes; 

public class ExtendedSqlServerDialect extends SQLServerDialect { 

    public ExtendedSqlServerDialect() { 
     registerFunction("weekdiff", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "datediff(week, ?2, ?1)")); 
    } 
} 

接着,就需要讓Hibernate使用這種方言(我使用的彈簧引導)。

application.yml

spring.jpa.properties.hibernate.dialect: com.xxx.dialect.ExtendedSqlServerDialect 

而且代碼示例我使用它,其中:

CriteriaBuilder cb /* = ... */; 
CriteriaQuery<Tuple> query = cb.createTupleQuery(); 
Root<Upload> root = query.from(Somewhere.class); 
query.groupBy(cb.function("weekdiff", 
    Integer.class, 
    root.get("creationDate"), 
    cb.parameter(String.class, "refDate")).alias("week") 
); 

而且因爲我使用我的單元測試HSQLDB,這裏對應的HSQLDB方言

import org.hibernate.dialect.SQLServerDialect; 
import org.hibernate.dialect.function.SQLFunctionTemplate; 
import org.hibernate.type.StandardBasicTypes; 

public class ExtendedHsqlDialect extends SQLServerDialect { 

    public ExtendedHsqlDialect() { 
     registerFunction("weekdiff", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "truncate(datediff('day', ?2, ?1)/7)")); 
    } 
} 

不幸的是,我不能對一組使用此功能By子句(見Why ORDER BY DATEDIFF raise an exception on SQL server using JPA?

相關問題