Tim*_*Tim 5 hibernate sql-function spring-data-jpa spring-boot
我的应用程序需要在Postgres,Mysql和测试Hsqldb之间移植.我已经设置了Flyway来为这三个提供一些自定义函数,我现在想在我的SQL/HQL查询中使用它们.
我目前的设置是使用Dialect我在之间切换的单独的s application-{profile}.yml; 哪个有效,但函数声明需要在各种方言之间重复,并且感觉不是最理想的.
看着15.29.Hibernate文档中的非标准化函数,它说我应该使用org.hibernate.cfg.Configuration#addSqlFunction(),它似乎更便携,并且无需扩展所有三种方言.
我的问题是:如何Configuration在Spring Boot(1.3)应用程序中访问Hibernate 类?默认情况下没有bean可以注入,也没有LocalSessionFactoryBeanbean.
任何人都可以指出我正确的方向,或以其他方式注册我的SQL函数一次?
小智 3
我对这个问题有一个破解方法。
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;
Run Code Online (Sandbox Code Playgroud)
第一个字段代表数据库的方言。第二个包含用户定义的函数,可以通过org.hibernate.cfg.Configuration#addSqlFunction().
不幸的是,在我搜索 hibernate 源代码时,我发现初始化 hibernate 时创建的配置对象没有以任何方式公开。
但是,我设法访问 SQLFunctionRegistry。
需要创建一个 EntityManagerFactory 类型的本地自动装配字段
@Autowired
private EntityManagerFactory emFactory;
Run Code Online (Sandbox Code Playgroud)
然后调用以下代码:
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)"));
}
Run Code Online (Sandbox Code Playgroud)
由于userFunctions字段是私有的并且未在类中公开,因此我使用 ReflectionUtils 来获取其值。它通常是空的,我只是向其中添加我的数据库函数。
因为我必须进入SqlFunctionRegistry的内部,所以这是一个 hack,但我更喜欢它而不是创建新的数据库方言并搞乱它。
| 归档时间: |
|
| 查看次数: |
538 次 |
| 最近记录: |