Java JPA中的PostgreSQL函数字符串_agg

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

在PostgreSQL中,string\u agg(列,分隔符)允许聚合一些字符串。我尝试将它与JPA一起使用,但它不是JPA标准函数

注意:这是而不是标准生成器#concat()的等价物

所以,我试图告诉JPA这个函数存在,如下所示:

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 "