Skip to content

Support for projections on repository query methods #150

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

odrotbohm
Copy link
Member

QueryMethods now expose a ResourceProcessor which is exposes information about the final to be created object types which can either be DTOs containing a persistence constructor (see @PersistenceConstructor) or projection interfaces. The former are analyzed for constructor properties so that store implementations can use that information to create projected queries that return exactly the fields required for that DTO.

Projection interfaces are inspected, their properties are considered input properties and the same projection queries can be issued against the data store. If a projection contains dynamically calculated properties (i.e. it uses SpEL expressions via @value) the original entities have to be queried and can be projected during post processing.

ProjectionFactory now exposes a more advanced ProjectionInformation that has additional meta information about the projection type. ProxyProjectionFactory now refers to the BeanClassLoader instead of the ResourceLoader.

RepositoryFactory(Bean)Support now also implement BeanFactoryAware to forward the BeanFactory to the SpelAwareProxyProjectionFactory which in turn now gets handed into the QueryLookupStrategy as well as the QueryMethod.

Parameter now knows about a dynamic projection type, which is a query method parameter of type Class bound to a generic method parameter and will be used to determine the projection to be used on a per call basis.

QueryMethods now expose a ResourceProcessor which is exposes information about the final to be created object types which can either be DTOs containing a persistence constructor (see @PersistenceConstructor) or projection interfaces. The former are analyzed for constructor properties so that store implementations can use that information to create projected queries that return exactly the fields required for that DTO.

Projection interfaces are inspected, their properties are considered input properties and the same projection queries can be issued against the data store. If a projection contains dynamically calculated properties (i.e. it uses SpEL expressions via @value) the original entities have to be queried and can be projected during post processing.

ProjectionFactory now exposes a more advanced ProjectionInformation that has additional meta information about the projection type. ProxyProjectionFactory now refers to the BeanClassLoader instead of the ResourceLoader.

RepositoryFactory(Bean)Support now also implement BeanFactoryAware to forward the BeanFactory to the SpelAwareProxyProjectionFactory which in turn now gets handed into the QueryLookupStrategy as well as the QueryMethod.

Parameter now knows about a dynamic projection type, which is a query method parameter of type Class bound to a generic method parameter and will be used to determine the projection to be used on a per call basis.
@odrotbohm odrotbohm self-assigned this Dec 14, 2015
odrotbohm added a commit that referenced this pull request Dec 14, 2015
QueryMethods now expose a ResourceProcessor which is exposes information about the final to be created object types which can either be DTOs containing a persistence constructor (see @PersistenceConstructor) or projection interfaces. The former are analyzed for constructor properties so that store implementations can use that information to create projected queries that return exactly the fields required for that DTO.

Projection interfaces are inspected, their properties are considered input properties and the same projection queries can be issued against the data store. If a projection contains dynamically calculated properties (i.e. it uses SpEL expressions via @value) the original entities have to be queried and can be projected during post processing.

ProjectionFactory now exposes a more advanced ProjectionInformation that has additional meta information about the projection type. ProxyProjectionFactory now refers to the BeanClassLoader instead of the ResourceLoader.

RepositoryFactory(Bean)Support now also implement BeanFactoryAware to forward the BeanFactory to the SpelAwareProxyProjectionFactory which in turn now gets handed into the QueryLookupStrategy as well as the QueryMethod.

Parameter now knows about a dynamic projection type, which is a query method parameter of type Class bound to a generic method parameter and will be used to determine the projection to be used on a per call basis.

Original pull request: #150.
@odrotbohm odrotbohm closed this Dec 14, 2015
@odrotbohm odrotbohm deleted the issue/DATACMNS-89 branch January 12, 2016 07:09
@mbragg02
Copy link

mbragg02 commented Mar 2, 2017

Hi @olivergierke
Im in the process of upgrading our app and I've run into an issue related to these changes and I wonder if you could advise. We are upgrading from Spring data commons from 1.11.4.RELEASE -> 1.12.x / 1.13.x.

We have a hierarchical entity structure. e.g. ReasonLabel extends AbstractResolutionLabel
We have a table with a Discriminator Column for the name of the concrete type.
We have the following query which previously worked:

@Query("SELECT label FROM AbstractResolutionLabel label WHERE label.group.id = :groupId AND label.providerType = :providerType AND TYPE(label) = :clazz")
    <T extends AbstractResolutionLabel> List<T> findByGroupIdAndProviderTypeAndType(@Param("groupId") String groupId,
                                                                                    @Param("providerType") ProviderType providerType,
                                                                                    @Param("clazz") Class<T> clazz);

We are now getting the following error:

Caused by: org.hibernate.QueryException: Named parameter [clazz] not set
	at org.hibernate.query.internal.QueryParameterBindingsImpl.verifyParametersBound(QueryParameterBindingsImpl.java:234)
	at org.hibernate.query.internal.AbstractProducedQuery.beforeQuery(AbstractProducedQuery.java:1309)
	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1408)
	at org.hibernate.query.Query.getResultList(Query.java:146)
	at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:121)
	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)
	... 57 more

It appears that from this line: https://github.com/spring-projects/spring-data-commons/pull/150/files#diff-325a1f477d275feb68e9ffec76dc064eR200 the new isDynamicProjectionParameter is returning true, so the class parameter is not being bound - Because both the parameter type and return type (T) are both equal.

I appreciate this change has been here for some time now, so I will likely have to change my app code.. but was hoping you could possibly suggest an alternative for my scenario.
Many thanks

@schauder
Copy link
Contributor

schauder commented Mar 2, 2017

With a quick glance at it, this sounds like a bug. Can you create a proper issue in Jira (https://jira.spring.io), please?

@mbragg02
Copy link

mbragg02 commented Mar 7, 2017

Thanks @schauder I created an issue: https://jira.spring.io/browse/DATACMNS-1002 cc @olivergierke

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants