2017-07-27 93 views
2

我有两个不与外键相关的实体。Spring Data JPA - 通过定义投影来加入不相关的实体

@Entity 
@Table(name = "attachment") 
public class Attachment implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    private UUID id; 

    @Column(name = "name") 
    private String name; 

    @Column(name = "ref_id") 
    private UUID refId; 

    @Column(name = "url") 
    private String url; 

    // getter/setter 
} 

我已经创建了投影

public interface ComplaintEntryProjection { 

    String getNote(); 

    EntryType getEntryType(); 

    ZonedDateTime getEntryDate(); 

    Boolean getInternalEntry(); 

    List<Attachment> getAttachments(); 
} 

和存储库

ComplaintEntry

@Entity 
@Table(name = "complaint_entry") 
public class ComplaintEntry implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    private UUID id; 

    @Column(name = "note") 
    private String note;  

    @Enumerated(EnumType.STRING) 
    @Column(name = "entry_type") 
    private EntryType entryType; 

    @Column(name = "entry_date") 
    private ZonedDateTime entryDate; 

    @Column(name = "internal_entry") 
    private Boolean internalEntry; 

    // getter/setter 
} 

附件

@Repository 
public interface ComplaintEntryRepository extends JpaRepository<ComplaintEntry,UUID> { 

    @Query("select complaintEntry, attachment from ComplaintEntry complaintEntry left join Attachment attachment " + 
      "on complaintEntry.id = attachment.refId where complaintEntry.internalEntry = true") 
    List<ComplaintEntryProjection> findAllByInternalEntryTrueForProjection(); 
} 

但是当我执行我的代码时,它没有按预期工作。

的这个堆栈跟踪是

org.springframework.dao.InvalidDataAccessApiUsageException: No aliases found in result tuple! Make sure your query defines aliases!; nested exception is java.lang.IllegalStateException: No aliases found in result tuple! Make sure your query defines aliases! 
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:381) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:488) 
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) 
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) 
    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.$Proxy167.findAllByInternalEntryTrueForProjection(Unknown Source) 
    at com.yoursafehub.web.controller.TimelineController.getComplaintPage(TimelineController.java:71) 
    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:97) 
    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:967) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) 
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129) 
    at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:111) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) 
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) 
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) 
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) 
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) 
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) 
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) 
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) 
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.servlet.handlers.SessionRestoringHandler.handleRequest(SessionRestoringHandler.java:143) 
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292) 
    at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81) 
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138) 
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135) 
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) 
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) 
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272) 
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) 
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104) 
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:211) 
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:809) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: java.lang.IllegalStateException: No aliases found in result tuple! Make sure your query defines aliases! 
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter.convert(AbstractJpaQuery.java:282) 
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:212) 
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter$1.convert(ResultProcessor.java:200) 
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:212) 
    at org.springframework.data.repository.query.ResultProcessor.processResult(ResultProcessor.java:149) 
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:121) 
    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:56) 
    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) 
    ... 123 common frames omitted 

我想这两个实体的数据读取到一个单一的投影。 这是做正确的方式或有任何其他方式。

编辑1:

  1. 我不想定义这些实体之间的关系(数据应该是针对ComplaintEntry和附件的REFID的ID匹配)。
  2. 一个ComplaintEntry可以有很多附件。
  3. 我想要一个像它包含ComplaintEntry字段和一个附件列表(像我上面定义的)的投影。

编辑2:

正如@ Cepr0在他answer的建议,我必须设置别名。现在设置别名后,没有例外,但结果不是我所期待的。 现在我查询更新为:

@Repository 
public interface ComplaintEntryRepository extends JpaRepository<ComplaintEntry,Integer> { 

    @Query("select ce.id as id, ce.note as note, ce.entryDate as entryDate, ce.internalEntry as internalEntry, " + 
     "a as attachments from ComplaintEntry ce left join Attachment a on ce.id = a.refId where ce.internalEntry = true") 
    List<ComplaintEntryProjection> findAllByInternalEntryTrueForProjection(); 
} 

和这样做的结果是:

[ { 
    "note" : "complaint entry one", 
    "entryType" : "COMMENT", 
    "entryDate" : "2017-07-30T13:26:34+05:30", 
    "internalEntry" : true, 
    "attachments" : [ { 
    "id" : 1, 
    "name" : "attachment one", 
    "refId" : 1, 
    "url" : "url1" 
    } ] 
}, { 
    "note" : "complaint entry one", 
    "entryType" : "COMMENT", 
    "entryDate" : "2017-07-30T13:26:34+05:30", 
    "internalEntry" : true, 
    "attachments" : [ { 
    "id" : 2, 
    "name" : "attachment two", 
    "refId" : 1, 
    "url" : "url2" 
    } ] 
} ] 

我需要的是单complaintEntry包含多个附件,这样的事情:

[ { 
    "note" : "complaint entry one", 
    "entryType" : "COMMENT", 
    "entryDate" : "2017-07-30T13:26:34+05:30", 
    "internalEntry" : true, 
    "attachments" : [ { 
    "id" : 1, 
    "name" : "attachment one", 
    "refId" : 1, 
    "url" : "url1" 
    }, 
    { 
    "id" : 2, 
    "name" : "attachment two", 
    "refId" : 1, 
    "url" : "url2" 
    } ] 
} ] 

是否有可能像这样获取数据。

+0

我认为你正在使用投影走错了路...... – Lino

+0

能否请你告诉我正确的方式。 –

+0

我猜“选择complaintEntry,附件”是错误的方法。您应该选择单个条目。就我所知,Projection用于Criteria。为什么不在ComplianceEntry和Attachment之间添加双向引用?根据JPA规范的 –

回答

2

正如InvalidDataAccessApiUsageException说:

在结果的元组中找不到别名!确保你的查询定义了别名!;

所以你刚刚设置aliases在您的查询,例如:

@Query("select ce as complaintEntry, a as attachment from ComplaintEntry ce left join Attachment a on ce.id = a.refId where ce.internalEntry = true") 
    List<ComplaintEntryAndAtachment> findComplaintEntryAndAtachment(); 

public interface ComplaintEntryAndAtachment { 

    ComplaintEntry getComplaintEntry(); 
    Attachment getAttachment(); 
} 
+0

感谢您的帮助。使用别名后,我删除了异常,但我无法获取我在问题中提到的格式的数据。更新我的问题,请看看。 –