Querydsl: GROUP_CONCAT NO funciona en QueryDSL

Creado en 12 nov. 2018  ·  6Comentarios  ·  Fuente: querydsl/querydsl

Hola,

Estoy luchando por descubrir cómo usar 'GROUP_CONCAT' en QueryDSL.

final QDataSourceSmallEliminate eliminate = QDataSourceSmallEliminate.dataSourceSmallEliminate;
        final QLattitudeVisitor lattitude = LattitudeVisitorServiceImpl.$;
//      Expressions.stringOperation(SQLOps.GROUP_CONCAT, lattitude.tagName)

        return QuerydslUtils.newQuery(entityManager).select(Projections.constructor(EliminateLattitude.class, 
                eliminate.id, 
                JPAExpressions.selectDistinct( SQLExpressions.groupConcat(lattitude.tagName)).from(lattitude).where(lattitude.urlCrc.eq(eliminate.urlCrc))))
            .from(eliminate)
            .fetch();

Excepción:

org.springframework.dao.InvalidDataAccessApiUsageException: No pattern found for GROUP_CONCAT; nested exception is java.lang.IllegalArgumentException: No pattern found for GROUP_CONCAT

...

Caused by: java.lang.IllegalArgumentException: No pattern found for GROUP_CONCAT
    at com.querydsl.core.support.SerializerBase.visitOperation(SerializerBase.java:280)
    at com.querydsl.jpa.JPQLSerializer.visitOperation(JPQLSerializer.java:437)
    at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:231)
    at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:31)
    at com.querydsl.core.types.OperationImpl.accept(OperationImpl.java:83)
    at com.querydsl.core.support.SerializerBase.handle(SerializerBase.java:92)
    at com.querydsl.jpa.JPQLSerializer.serialize(JPQLSerializer.java:203)
    at com.querydsl.jpa.JPQLSerializer.visit(JPQLSerializer.java:358)
    at com.querydsl.jpa.JPQLSerializer.visit(JPQLSerializer.java:39)
    at com.querydsl.core.types.SubQueryExpressionImpl.accept(SubQueryExpressionImpl.java:57)
    at com.querydsl.core.support.FetchableSubQueryBase.accept(FetchableSubQueryBase.java:150)
    at com.querydsl.core.support.SerializerBase.handle(SerializerBase.java:92)
    at com.querydsl.core.support.SerializerBase.handle(SerializerBase.java:119)
    at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:225)
    at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:31)
    at com.querydsl.core.types.ConstructorExpression.accept(ConstructorExpression.java:112)
    at com.querydsl.core.support.SerializerBase.handle(SerializerBase.java:92)
    at com.querydsl.jpa.JPQLSerializer.serialize(JPQLSerializer.java:203)
    at com.querydsl.jpa.JPAQueryBase.serialize(JPAQueryBase.java:60)
    at com.querydsl.jpa.JPAQueryBase.serialize(JPAQueryBase.java:50)
    at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:98)
    at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:94)
    at com.querydsl.jpa.impl.AbstractJPAQuery.fetch(AbstractJPAQuery.java:201)
    at com.moraydata.general.secondary.repository.impl.DataSourceSmallEliminateRepositoryImpl.findObject(DataSourceSmallEliminateRepositoryImpl.java:98)
    at com.moraydata.general.secondary.repository.impl.DataSourceSmallEliminateRepositoryImpl$$FastClassBySpringCGLIB$$b42d875d.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)

QueryDSL 4.2.1 y JDK1.8 y Spring Boot2.0 y MySQL 5.7.

Leí el último documento de referencia y todavía no puedo encontrar la respuesta, entonces, ¿qué debo hacer para que funcione?

Por favor ayuda.
Gracias por adelantado.
@ Shredder121

jpa question

Comentario más útil

@beamofsoul

si usa Spring Boot Data jpa y querydsl-jpa , puede seguir estos pasos

  1. crear un dialecto DB personalizado y una función de registro
//  org.hibernate.dialect.MySQL5Dialect
public class CustomMysqlDialect extends MySQL5Dialect {
    public CustomMysqlDialect() {
        super();
        // register custom/inner function here
        this.registerFunction("group_concat", new SQLFunctionTemplate(StandardBasicTypes.STRING, "group_concat(?1)"));
    }
}
  1. config JpaVendorAdapter
<strong i="15">@Configuration</strong>
public class JpaConfiguration {
    <strong i="16">@Bean</strong>
    public JpaVendorAdapter jpaVendorAdapter() {
        AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(true);
        adapter.setDatabase(Database.MYSQL);
       // package to CustomMysqlDialect
        adapter.setDatabasePlatform("com.xxx.xxx.config.CustomMysqlDialect");
        adapter.setGenerateDdl(false);
        return adapter;
    }
}
  1. utilizar query-dsl
// before do this , autowird JPAQueryFactory at first 
        QReportDoctorTag qReportDoctorTag = QReportDoctorTag.reportDoctorTag;
        SimpleTemplate<String> simpleTemplate = Expressions.simpleTemplate(String.class, "group_concat({0})", qReportDoctorTag.tag);
        JPAQuery<Tuple> tupleJPAQuery = queryFactory.select(qReportDoctorTag.reportId, simpleTemplate)
                .from(qReportDoctorTag)
                .groupBy(qReportDoctorTag.reportId);

        List<Tuple> fetch = tupleJPAQuery.fetch();

Todos 6 comentarios

No siempre se pueden mezclar JPAExpressions y SQLExpressions.

No siempre se pueden mezclar JPAExpressions y SQLExpressions.

Sí, amigo, tienes razón. No tengo ni idea de cómo solucionar este problema, solo intente algo que pueda ser útil.
Entonces, ¿cómo puedo lidiar con eso si necesito GROUP_CONCAT cuando uso JPAExpressions?

@beamofsoul

si usa Spring Boot Data jpa y querydsl-jpa , puede seguir estos pasos

  1. crear un dialecto DB personalizado y una función de registro
//  org.hibernate.dialect.MySQL5Dialect
public class CustomMysqlDialect extends MySQL5Dialect {
    public CustomMysqlDialect() {
        super();
        // register custom/inner function here
        this.registerFunction("group_concat", new SQLFunctionTemplate(StandardBasicTypes.STRING, "group_concat(?1)"));
    }
}
  1. config JpaVendorAdapter
<strong i="15">@Configuration</strong>
public class JpaConfiguration {
    <strong i="16">@Bean</strong>
    public JpaVendorAdapter jpaVendorAdapter() {
        AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(true);
        adapter.setDatabase(Database.MYSQL);
       // package to CustomMysqlDialect
        adapter.setDatabasePlatform("com.xxx.xxx.config.CustomMysqlDialect");
        adapter.setGenerateDdl(false);
        return adapter;
    }
}
  1. utilizar query-dsl
// before do this , autowird JPAQueryFactory at first 
        QReportDoctorTag qReportDoctorTag = QReportDoctorTag.reportDoctorTag;
        SimpleTemplate<String> simpleTemplate = Expressions.simpleTemplate(String.class, "group_concat({0})", qReportDoctorTag.tag);
        JPAQuery<Tuple> tupleJPAQuery = queryFactory.select(qReportDoctorTag.reportId, simpleTemplate)
                .from(qReportDoctorTag)
                .groupBy(qReportDoctorTag.reportId);

        List<Tuple> fetch = tupleJPAQuery.fetch();

Para SQL, use SQLExpressions.groupConcat . Para JPA esto no es compatible, porque GROUP_CONCAT no es una función definida para JPQL. Ninguno de los proveedores de ORM lo envía de forma predeterminada, aunque la función se puede registrar manualmente en algunos casos (consulte el ejemplo en el comentario anterior).

Duplicado de # 2020.

@ giraffe-tree Hola, quiero usar "GROUP_CONCAT ({0} ORDER BY {1})", ¿cómo registrar la función? Por favor.

En JPA esto no es compatible. Tendrá que pedirle a su proveedor de ORM que lo implemente primero (por ejemplo, Hibernate).

Podría considerar usar la extensión blaze-persistence-querydsl para llenar el vacío: https://persistence.blazebit.com/documentation/1.5/core/manual/en_US/index.html#querydsl -integration

Que tiene los siguientes métodos:

  • JPQLNextExpressions.groupConcat(Expression<?> expression, String separator, OrderSpecifier<?>... orderSpecifiers)
  • JPQLNextExpressions.groupConcat(Expression<?> expression, Expression<String> separator, OrderSpecifier<?>... orderSpecifiers)
  • JPQLNextExpressions.groupConcat(boolean distinct, Expression<?> expression, String separator, OrderSpecifier<?>... orderSpecifiers)
  • JPQLNextExpressions.groupConcat(boolean distinct, Expression<?> expression, Expression<String> separator, OrderSpecifier<?>... orderSpecifiers)
¿Fue útil esta página
0 / 5 - 0 calificaciones