2016-08-19 56 views
4

我的應用程序需要在Postgres,Mysql和測試Hsqldb之間移植。我已經設置了Flyway以在所有三個上都提供一些自定義函數,現在我想在我的SQL/HQL查詢中使用它們。如何在Spring Boot應用程序中添加非標準化的SQL函數?

我目前的設置使用單獨的Dialect s,我使用application-{profile}.yml進行切換;哪個起作用,但函數聲明需要在各種方言中重複,並且感覺不太理想。

在Hibernate文檔中查看15.29. Non-standardized functions,它說我應該使用org.hibernate.cfg.Configuration#addSqlFunction(),這看起來更加便攜並且不需要擴展所有三種方言。

我的問題是:我如何在Spring Boot(1.3)應用程序中訪問Hibernate Configuration類?默認情況下沒有bean注入,也沒有bean注入。

任何人都可以指向正確的方向,或以其他方式註冊我的SQL函數一次嗎?

回答

1

我對這個問題頗爲詬病。

Hibernate使用org.hibernate.dialect.Dialect.SQLFunctionRegistry來識別DB功能。

這裏是一個hibernate core 4.3.10的例子。 內部,它包含兩個私有字段:

/** 
* Defines a registry for SQLFunction instances 
* 
* @author Steve Ebersole 
*/ 
public class SQLFunctionRegistry { 
    private final Dialect dialect; 
    private final Map<String, SQLFunction> userFunctions; 

第一個字段表示數據庫的方言。 其次包含可由org.hibernate.cfg.Configuration#addSqlFunction()填充的用戶定義函數。

不幸的是,在通過hibernate源代碼搜索時,我發現在初始化hibernate時創建的配置對象沒有以任何方式公開。

但是,我設法訪問SQLFunctionRegistry。

一個需要創建類型的局部自動裝配Autowired場的EntityManagerFactory

@Autowired 
private EntityManagerFactory emFactory; 

後來調用下面的代碼:

private void registerMyDbFunctions() 
{ 
    SQLFunctionRegistry registry = this.emFactory.unwrap(org.hibernate.internal.SessionFactoryImpl.class).getSqlFunctionRegistry(); 
    Field field = ReflectionUtils.findField(SQLFunctionRegistry.class, "userFunctions"); 
    ReflectionUtils.makeAccessible(field); 
    Map<String, SQLFunction> userFunctions = (Map<String, SQLFunction>)ReflectionUtils.getField(field, registry); 

    userFunctions.put("my_func", new SQLFunctionTemplate(TextType.INSTANCE, "my_func(?1, ?2)")); 
} 

由於userFunctions領域是私人的,在課堂上不外露,我用ReflectionUtils獲得它的價值。它通常是空的,我只是添加我的數據庫功能。

由於我不得不進入SqlFunctionRegistry的內部,這是一種黑客攻擊,但我更喜歡創建新的DB方言並搞亂它。

相關問題