2017-03-02 2 views
3

Meine Anforderung besteht darin, alle Image (WAHImage) -Objekte abzurufen, ob die Probe (SpecimenImpl) null ist oder nicht, ob der Taxoname (WACensusImpl) null ist oder nicht, und Reihenfolge das Ergebnis nach Probenname oder Taxonamen, falls verfügbar, und Anzeigen der Bildobjekte mit einer Nullprobe und einem Nulltaxonnamen zuerst.Modellobjekte nach Eigenschaften von nullbaren untergeordneten Objekten in QueryDSL ordnen

Mit dem folgenden Code erhalte ich einen Fehler No property coalesce(wAHimage found for type WAHImage.

Es ist ziemlich klar, dass mein Anwendungsfall not (yet) fully supported in QueryDSL ist, nämlich die Fähigkeit, nach einer Entität abzufragen und die resultierenden Objekte nach Eigenschaften ihrer nullbaren untergeordneten Objekte zu ordnen. Dies liegt daran, dass QueryDSL CROSS JOINs anstelle von LEFT JOINs verwendet und Sie nicht nach untergeordneten Objekteigenschaften mit einem CROSS JOIN sortieren können. Dies scheint die Quelle meiner Frustration zu sein, und ich suche jetzt nach anderen Lösungen, anstatt bei QueryDSL zu bleiben.

Spring Data JPA Repository:

public interface ImageRepository extends JpaRepository<WAHImage, Long>, 
     QueryDslPredicateExecutor<WAHImage> { 
    Page<WAHImage> findAllByIsDeleted(boolean isDeleted, Pageable page); 
} 

Frühling Boot (1.5.1) Service, der ImageRepository in seinem Konstruktor autowired hat:

@Service 
public class ImageService { 
    private ImageRepository imageRepository; 
    public Page<WAHImage> get(Pageable pageable) { 
     return imageRepository.findAllByIsDeleted(false, ImagePredicates.orderByName(pageable)); 
    } 

ImagePredicates.orderByName (Pageable):


Controller:

@Controller 
public class ImageController { 
    @GetMapping("/list") 
    public String list(Pageable pageable, Model model) { 
     Page<WAHImage> searchResult = imageService.get(pageable); 
    } 
} 

Der Fehler:

org.springframework.data.mapping.PropertyReferenceException: No property coalesce(wAHImage found for type WAHImage! 
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77) 
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:329) 
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:309) 
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:272) 
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:243) 
at org.springframework.data.jpa.repository.query.QueryUtils.toJpaOrder(QueryUtils.java:542) 
at org.springframework.data.jpa.repository.query.QueryUtils.toOrders(QueryUtils.java:496) 
at org.springframework.data.jpa.repository.query.JpaQueryCreator.complete(JpaQueryCreator.java:195) 
at org.springframework.data.jpa.repository.query.JpaQueryCreator.complete(JpaQueryCreator.java:143) 
at org.springframework.data.jpa.repository.query.JpaQueryCreator.complete(JpaQueryCreator.java:52) 
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:88) 
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:144) 
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.doCreateQuery(PartTreeJpaQuery.java:79) 
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.createQuery(AbstractJpaQuery.java:190) 
at org.springframework.data.jpa.repository.query.JpaQueryExecution$PagedExecution.doExecute(JpaQueryExecution.java:184) 
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:85) 
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:116) 
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106) 
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:483) 
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 
at com.sun.proxy.$Proxy143.findAllByIsDeleted(Unknown Source) 
at x.y.z.image.ImageService.get(ImageService.java:120) 
at x.y.z.image.ImageService$$FastClassBySpringCGLIB$$6d3a7999.invoke(<generated>) 
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:652) 
at x.y.z.image.ImageService$$EnhancerBySpringCGLIB$$21037cfe.get(<generated>) 
at x.y.z.controller.image.ImageController.list(ImageController.java:132) 
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.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) 
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) 
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) 
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) 
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) 
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 

Relevante Teile WAHImage Modellklasse.

@Entity 
@Table(name = "image") 
public class WAHImage extends PersistentImpl { 
    private WACensusImpl census = new WACensusImpl(); 
    private SpecimenImpl specimen = new SpecimenImpl(); 
    private boolean isDeleted = Boolean.FALSE; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "census_id", nullable = true) 
    public WACensusImpl getCensus() { 
     return census; 
    } 

    public void setCensus(WACensusImpl census) { 
     this.census = census; 
    } 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "specimen_id", nullable = true) 
    public SpecimenImpl getSpecimen() { 
     return specimen; 
    } 

    public void setSpecimen(SpecimenImpl specimen) { 
     this.specimen = specimen; 
    } 

    @Column(name = "is_deleted") 
    public boolean getIsDeleted() { 
     return isDeleted; 
    } 

    public void setIsDeleted(boolean isDeleted) { 
     this.isDeleted = isDeleted; 
    } 

} 

Relevante Teile QWAHImage QueryDSL Klasse.

/** 
* QWAHImage is a Querydsl query type for WAHImage 
*/ 
@Generated("com.querydsl.codegen.EntitySerializer") 
public class QWAHImage extends EntityPathBase<WAHImage> { 

    public static final QWAHImage wAHImage = new QWAHImage("wAHImage"); 

    public final x.y.z.db.impl.QPersistentImpl _super = new x.y.z.db.impl.QPersistentImpl(this); 

    public final x.y.z.reference.census.impl.QWACensusImpl census; 

    //inherited 
    public final NumberPath<Long> id = _super.id; 

    public final BooleanPath isDeleted = createBoolean("isDeleted"); 

    public final x.y.z.reference.specimen.impl.QSpecimenImpl specimen; 
} 

Relevante Teile QWACensusImpl:

/** 
* QWACensusImpl is a Querydsl query type for WACensusImpl 
*/ 
@Generated("com.querydsl.codegen.EntitySerializer") 
public class QWACensusImpl extends EntityPathBase<WACensusImpl> { 

    public static final QWACensusImpl wACensusImpl = new QWACensusImpl("wACensusImpl"); 

    public final x.y.z.db.impl.QPersistentWithIDImpl _super = new x.y.z.db.impl.QPersistentWithIDImpl(this); 

    //inherited 
    public final NumberPath<Long> id = _super.id; 

    public final StringPath name1 = createString("name1"); 

    public final StringPath name2 = createString("name2"); 

    public final StringPath name3 = createString("name3"); 

    public final StringPath name4 = createString("name4"); 

    // extraneous parts omitted. 
} 
+0

bitte aussetzen Ihre 'Pageable' Modell und' findAllByIsDeleted (...) 'Methode Implementierung. –

+0

Das 'Pageable' ist ein Standard' org.springframework.data.domain."Imaging", das von Spring an meinen 'ImageController' geliefert wird, ist dies normalerweise eine Spring' PageRequest'-Instanz. 'ImageRepository' ist ein [Spring Data JpaRepository] (http://docs.spring.io/spring-data/jpa/docs/1.11.1.RELEASE/reference/html/#repositories.core-concepts), welches ein Implementation by Design erstellt Spring Data automatisch eine konkrete Klasse. – ben3000

+0

Setzen Sie den vollständigen Entitätscode und auch für die QWACensusImpl-Entität. –

Antwort

0

Nach einiger umfangreichen Hintergrund Forschung scheint es, dass mein Anwendungsfall hat a long history und bleibt ein common one.

Um dies zu beheben, konnte ich (a) get access to the EntityManager in Spring Data JPA und von dort baut die Abfrage mit LEFT JOINs, nach, dass ich das COALESCE Stichwort in ImagePredicates.orderByName(Pageable) nutzen kann.

Alternativ (und der Ansatz, den ich entschieden haben, zu verwenden) Ich benutze einen Spring Data @Query auf ImageRepository.findAllByIsDeleted(boolean, Pageable):

public interface ImageRepository extends JpaRepository<WAHImage, Long>, 
     QueryDslPredicateExecutor<WAHImage> { 
    @Query("select i from WAHImage i " + 
      "left join i.specimen s " + 
      "left join i.census c " + 
      "left join i.author a " + 
      "left join i.copyright co " + 
      "left join i.allowedUse au " + 
      "where i.isDeleted = ?1 " + 
      "order by coalesce(s.genus, c.name1) asc, " + 
      "coalesce(s.species, c.name2) asc, " + 
      "coalesce(s.infraspecies, c.name4, c.name3) asc") 
    Page<WAHImage> findAllByIsDeleted(boolean isDeleted, Pageable page); 
} 
Verwandte Themen