Java JPA中的PostgreSQL函数字符串_agg
在PostgreSQL中,string\u agg(列,分隔符)允许聚合一些字符串。我尝试将它与JPA一起使用,但它不是JPA标准函数 注意:这是而不是标准生成器#concat()的等价物 所以,我试图告诉JPA这个函数存在,如下所示:Java JPA中的PostgreSQL函数字符串_agg,java,postgresql,jpa,Java,Postgresql,Jpa,在PostgreSQL中,string\u agg(列,分隔符)允许聚合一些字符串。我尝试将它与JPA一起使用,但它不是JPA标准函数 注意:这是而不是标准生成器#concat()的等价物 所以,我试图告诉JPA这个函数存在,如下所示: public class StringAgg extends ParameterizedFunctionExpression<String> implements Serializable { public static final Strin
public class StringAgg extends ParameterizedFunctionExpression<String> implements Serializable {
public static final String NAME = "string_agg";
@Override
public boolean isAggregation() {
return true;
}
@Override
protected boolean isStandardJpaFunction() {
return false;
}
public StringAgg(CriteriaBuilderImpl criteriaBuilder, Expression<String> expression, String separator) {
super(criteriaBuilder, String.class, NAME, expression, new LiteralExpression(criteriaBuilder, separator));
}
}
在persistence.xml中使用它
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="hibernate.dialect" value="path.to.PGDialect"/>
然后使用标准生成器函数():
Expression<String> exprStr = ...
CriteriaBuilder cb = ...
cb.construct(MyClass.class,
myClass.get(MyClass_.name),
myClass.get(MyClass_.surname),
cb.function( "string_agg", myColPath, cb.literal("delimiter" )));
表达式exprStr=。。。
CriteriaBuilder cb=。。。
cb.construct(MyClass.class,
myClass.get(myClass.name),
myClass.get(myClass.姓氏),
函数(“string_agg”,myColPath,cb.literal(“delimiter”);
为了简化,我创建了一个助手方法:
public static Expression<String> strAgg(CriteriaBuilder cb, Expression<String> expression, String delimiter) {
return cb.function( "string_agg", String.class, expression, cb.literal(delimiter));
}
公共静态表达式strAgg(CriteriaBuilder cb、表达式表达式、字符串分隔符){
返回cb.function(“string_agg”、string.class、表达式、cb.literal(分隔符));
}
因此,代码变成:
Expression<String> exprStr = ...
CriteriaBuilder cb = ...
cb.construct(MyClass.class,
myClass.get(MyClass_.name),
myClass.get(MyClass_.surname),
strAgg(cb, myColPath, "delimiter"));
表达式exprStr=。。。
CriteriaBuilder cb=。。。
cb.construct(MyClass.class,
myClass.get(myClass.name),
myClass.get(myClass.姓氏),
strAgg(cb,myColPath,“分隔符”);
也许这对你有帮助
您可以在JPA条件查询中调用数据库函数
CriteriaBuilder界面具有“”方法
并在CriteriaBuilder中将其作为普通函数使用
Expression<String> functionStringAgg = cb.function( "string_agg", String.class,
cb.parameter(String.class, "toJoin" ),
cb.parameter(String.class, "delimiter"));
我使用相同的结构,但方法很简单: 修改了持久性文件:
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">es.gmrcanarias.saga.utiles.PGDialect</prop>
<prop key="hibernate.show_sql">true</prop>
...
</props>
</property>
然后添加了查询:
Join<Razon, Incidenc> subquery;
....
Expression<String> functionStringAgg = criteriaBuilder.function("string_agg",
String.class,
subquery.get(CODIGO),
criteriaBuilder.literal(", "));
...
subqueryList.select(functionStringAgg);
Join子查询;
....
表达式functionStringAgg=criteriaBuilder.function(“string\u agg”,
String.class,
subquery.get(CODIGO),
criteriaBuilder.literal(“,”);
...
选择(functionStringAgg);
PG方言的一个细节:
您可以添加第三个参数以使用ORDER BY
public class PGDialect extends PostgreSQL9Dialect {
public PGDialect() {
super();
this.registerFunction("string_agg", new SQLFunctionTemplate( StandardBasicTypes.STRING, "string_agg(?1, ?2)") );
this.registerFunction("string_agg", new SQLFunctionTemplate( StandardBasicTypes.STRING, "string_agg(?1, ?2 ORDER BY ?3 )") );
}
}
HQL查询用法
"SELECT string_agg(f.name, '; ', f.name) FROM Foo as f "
函数是JPA(2.1)标准函数。也许可以使用它为什么不使用类的普通构造函数,相当于JPQL中的
selectnewcom.me.Entity(path1,path2).
?(附言:+1,因为我学到了一些新东西)你摇滚:)第一个解决方案不起作用:我最终遇到了同样的问题。我的代码也差不多。但是通过一种新的方言注册这个函数非常有效。@Arnaud Denoyelle你能帮我吗issue@vzamanillo能否请您在stackoverflow.com/questions/55218784/…Issue上提供帮助我收到了以下错误`java.lang.IllegalStateException:节点没有数据类型:org.hibernate.hql.internal.ast.tree.MethodNode\-[METHOD\u CALL]MethodNode:'function(string_agg)'+-[METHOD_NAME]IdentNode:'string_agg'{originalText=string_agg}-[EXPR_LIST]SqlNode:'exprList'+-[NAMED_PARAM]ParameterNode:'?'{NAME=empId,expectedType=null}-[NAMED_PARAM]ParameterNode:'?'{NAME=delimiter,expectedType=null}}`
public class PGDialect extends PostgreSQLDialect{
public PGDialect() {
super();
registerFunction("string_agg", new SQLFunctionTemplate( StandardBasicTypes.STRING, "string_agg(?1, ?2)"));
}
}
Expression<String> functionStringAgg = cb.function( "string_agg", String.class,
cb.parameter(String.class, "toJoin" ),
cb.parameter(String.class, "delimiter"));
setParameter( "toJoin", toJoin);
setParameter( "delimiter", delimiter);
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">es.gmrcanarias.saga.utiles.PGDialect</prop>
<prop key="hibernate.show_sql">true</prop>
...
</props>
</property>
import org.hibernate.dialect.PostgreSQL82Dialect;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.type.StandardBasicTypes;
public class PGDialect extends PostgreSQL82Dialect {
public PGDialect() {
super();
registerFunction("string_agg", new
SQLFunctionTemplate(StandardBasicTypes.STRING, "string_agg(?1, ?2)"));
}
}
Join<Razon, Incidenc> subquery;
....
Expression<String> functionStringAgg = criteriaBuilder.function("string_agg",
String.class,
subquery.get(CODIGO),
criteriaBuilder.literal(", "));
...
subqueryList.select(functionStringAgg);
public class PGDialect extends PostgreSQL9Dialect {
public PGDialect() {
super();
this.registerFunction("string_agg", new SQLFunctionTemplate( StandardBasicTypes.STRING, "string_agg(?1, ?2)") );
this.registerFunction("string_agg", new SQLFunctionTemplate( StandardBasicTypes.STRING, "string_agg(?1, ?2 ORDER BY ?3 )") );
}
}
"SELECT string_agg(f.name, '; ', f.name) FROM Foo as f "