我需要将Spring Data JPA / Hibernate应用程序迁移到
MS SQL Server (Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64)
Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (Hypervisor))
来自
Oracle(Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production).
环境:
org.springframework.data:spring-data-jpa:2.0.9.RELEASE
org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final
org.hibernate:hibernate-entitymanager:5.2.17.Final
Java version: 1.8.0_91, vendor: Oracle Corporation
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
现在在orm.xml中的许多地方,我们都使用了 to_char 。例如,生成每月的汇总报告等。
在SQL Server架构中,我们定义了 to_char ,希望Hibernate会注册它或留下一些钩子来注册用户定义的函数:
CREATE FUNCTION to_char(@dateVal DATE, @dateFormat varchar) RETURNS VARCHAR(20)
BEGIN
RETURN CONVERT(varchar, date, 1)
END
我研究了Write & Call user-defined function in JPQL?。但不幸的是,我不允许重新定义一种方言。
对于JPQL,
<query>
select new com.entity.MyEntity(
c.Id,
to_char(c.transactionDate,'Mon/yyyy'),
sum(c.disputeAmount))
FROM ChargeBack c join c.chargebackReason rcd
GROUP BY c.Id, to_char(c.transactionDate,'Mon/yyyy'),
</query>
由于未注册SQL函数,出现以下错误。
Caused by: java.lang.NullPointerException
at org.hibernate.hql.internal.NameGenerator.generateColumnNames(NameGenerator.java:27)
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.generateColumnNames(SessionFactoryHelper.java:434)
at org.hibernate.hql.internal.ast.tree.SelectClause.initializeColumnNames(SelectClause.java:269)
at org.hibernate.hql.internal.ast.tree.SelectClause.finishInitialization(SelectClause.java:259)
at org.hibernate.hql.internal.ast.tree.SelectClause.initializeExplicitSelectClause(SelectClause.java:254)
at org.hibernate.hql.internal.ast.HqlSqlWalker.useSelectClause(HqlSqlWalker.java:1013)
at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:781)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:677)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:313)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:266)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.query.spi.NamedQueryRepository.checkNamedQueries(NamedQueryRepository.java:157)
at org.hibernate.internal.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:533)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:323)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:462)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390)
... 67 more
答案 0 :(得分:1)
您的参考文献很旧,不再有效。从JPA 2.1开始,您可以像这样调用客户函数:
function('to_char', c.transactionDate,'Mon/yyyy')
所以您的查询应该像
<query>
select new com.entity.MyEntity(
c.Id,
function('to_char', c.transactionDate,'Mon/yyyy'),
sum(c.disputeAmount))
FROM ChargeBack c join c.chargebackReason rcd
GROUP BY c.Id, function('to_char', c.transactionDate,'Mon/yyyy'),
</query>