Java 无法在CriteriaBuilder构造方法内调用数据库函数
我将DTO类简化为只有两个属性:UUID和Long:Java 无法在CriteriaBuilder构造方法内调用数据库函数,java,hibernate,jpa,Java,Hibernate,Jpa,我将DTO类简化为只有两个属性:UUID和Long: public class MyDto implements Serializable { private UUID uuid; private Long sequential; // Constructor taking properties as parameters // Geters and setters } 当我尝试在CriteriaBuilder中进行如下构造时,我的代码非常有效: // A
public class MyDto implements Serializable {
private UUID uuid;
private Long sequential;
// Constructor taking properties as parameters
// Geters and setters
}
当我尝试在CriteriaBuilder中进行如下构造时,我的代码非常有效:
// Assuming my constructor in MyDto take only UUID parameter
query.select(builder.construct(MyDto.class,
root.get(MyDto_.uuid)));
但是,当我尝试在Dto的构造函数中添加“sequential”参数,并将我的select更改为从db函数中检索值时,如下所示:
// Assuming my constructor in MyDto take both UUID and Long parameters
query.select(builder.construct(MyDto.class,
builder.function("nextval", Long.class, builder.literal("my_seq")),
root.get(MyDto_.uuid)));
hibernate引发异常:
java.lang.NullPointerException
at org.hibernate.hql.internal.NameGenerator.generateColumnNames(NameGenerator.java:27)
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.generateColumnNames(SessionFactoryHelper.java:418)
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:991)
at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:759)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:675)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:311)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:259)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:262)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:190)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142)
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.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:545)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:654)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3282)
at org.hibernate.query.criteria.internal.CriteriaQueryImpl$1.buildCompiledQuery(CriteriaQueryImpl.java:318)
at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:127)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3575)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:204)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.weld.bean.proxy.AbstractBeanInstance.invoke(AbstractBeanInstance.java:38)
at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:100)
at org.jboss.weld.proxies.AutoCloseable$EntityManager$HibernateEntityManager$QueryProducer$Serializable$Session$SharedSessionContract$1645305853$Proxy$_$$_WeldClientProxy.createQuery(Unknown Source)
在我试图做的事情中,我看到函数在where中使用,但我需要在CriteriaBuilder的构造函数中使用
我有这个工作在旧的方式选择新的MyDto。。。但是我正在努力使用CriteriaBuilder。对于每个面临相同问题的人来说,答案是:注册你的函数 如中所述 在执行实体查询(例如JPQL、HQL或Criteria API)时,只要函数直接传递到基础SQL语句的WHERE子句,就可以使用任何SQL函数,而无需注册它。但是,如果在SELECT子句中使用了SQL函数,并且Hibernate尚未注册SQL函数(无论是特定于数据库的函数还是用户定义的函数),则必须先注册该函数,然后才能在实体查询中使用它 所以我需要做的是首先创建一个扩展我的方言的类,并在构造函数中注册我的函数
public class MyCustomPostgreSQLDialect extends org.hibernate.dialect.PostgreSQLDialect {
public MyCustomPostgreSQLDialect() {
super();
registerFunction("name_of_function",
new StandardSQLFunction("name_of_function",
StandardBasicTypes.BIG_DECIMAL // Or the appropriated result of the function
)
);
}
}
然后,将persistence.xml中的方言更改为带有注册函数的新自定义方言
<property name="hibernate.dialect" value="my.package.MyCustomPostgreSQLDialect"/>