Skip to content
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

Support for @QueryHints on CRUD methods [DATAJPA-173] #590

Closed
spring-projects-issues opened this issue Feb 15, 2012 · 12 comments
Closed

Support for @QueryHints on CRUD methods [DATAJPA-173] #590

spring-projects-issues opened this issue Feb 15, 2012 · 12 comments
Assignees
Labels
in: core type: enhancement

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Feb 15, 2012

Pascal Heus opened DATAJPA-173 and commented

Add support for @QueryHints annotations for CRUD methods such as findAll(…), findOne(…), etc. For complex hierarchical structure, having the option to fine tune joins would be highly beneficial in terms of performance


Reference URL: http://forum.springsource.org/showthread.php?113519-Query-Caching

Issue Links:

  • DATAJPA-507 Performance tuning LockModePopulatingMethodIntercceptor.invoke()

Referenced from: commits b71cd3e, 5438c44

9 votes, 10 watchers

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Dec 16, 2013

pascal gehl commented

Adding query hints for caching on CRUD methods (findAll, findOne...) seems to be a minimum feature, specially with ORM's second level caches. Do you have any timeline for this feature ?

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Dec 16, 2013

Dmitry Angelov commented

IMHO at least its worth to move its priority one level up

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 11, 2014

Jan Goyvaerts commented

Is there a straightforward way to work around this issue ? I have massive amounts of find-by-id queries only producing cache misses. The second level cache is filled but is never used.

Because findOne is not cached ?

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 11, 2014

Martin Maier-Moessner commented

You could write your own base repository class and override findOne() or create a new method findOneCached(). In your custom implementation you then have direct access to the javax.persistence.Query instance, which has the setHint()-method you want to use.

For details see http://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/htmlsingle/#repositories.custom-behaviour-for-all-repositories

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 12, 2014

Jan Goyvaerts commented

I've added:

@Transactional(readOnly = true, propagation = Propagation.MANDATORY, rollbackFor = Throwable.class)
public T findById(@NotNull final Long id) {
  return em.find(clazz, id, QUERY_HINTS);
}

Where clazz is the domain class of the constructor and QUERY_HINTS a static immutable map containing two Hibernate hints.

  private static final Map<String, Object> QUERY_HINTS;

  static {
    final Map<String, Object> map = new HashMap<String, Object>();
// The official JPA2 hints don't seem to work for Hibernate 4.2.8.Final
//  map.put("javax.persistence.cache.retrieveMode", CacheRetrieveMode.USE);
//  map.put("javax.persistence.cache.storeMode", CacheStoreMode.REFRESH);
    map.put("org.hibernate.cacheable", true);
    map.put("org.hibernate.cacheMode", CacheMode.NORMAL);
    QUERY_HINTS = Collections.unmodifiableMap(map);
  }

Making a query each each call is way too slow for me. Hence the usage of EntityManager.find()

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 12, 2014

Oliver Drotbohm commented

That's in place for the 1.6.0.BUILD-SNAPSHOTS. Feel free to give this a spin. I extended the previously existing infrastructure to detect @Lock annotations to detect @QueryHints as well.

I also added some caching of the metadata to make sure we don't waste too much time for reflection based annotation lookup for every method invocation.

We're shooting for an M1 by some time next week, so it'd be incredibly helpful to get some feedback about this

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 13, 2014

Jan Goyvaerts commented

I'll have a go today - I have other cats to skin, but I will be the last to discourage such speedy support ! :-)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 13, 2014

Jan Goyvaerts commented

A bit of a hassle to upgrade from 1.4

=> new methods
=> relocated classes
=> wrong version of Data Common
=> errors against the usage of JsonProperty of Jackson.

But here we are !

I'm getting NPE at SimpleJpaRepository.applyRepositoryMethodMetadata(), line 528. Variable "crudMethodMetadata" is null.

Anything I can try ?

====================================================

java.lang.NullPointerException
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.applyRepositoryMethodMetadata(SimpleJpaRepository.java:528)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:475)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:268)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:358)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:111)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy126.findAll(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
at com.sun.proxy.$Proxy127.findAll(Unknown Source)
at com.noesis.optimus.services.ProjectServiceImpl.findAll(ProjectServiceImpl.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
etc...

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 13, 2014

Oliver Drotbohm commented

Which versions are you using exactly?

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 13, 2014

Jan Goyvaerts commented

spring-data-commons-1.8.0.BUILD-20140311.113611-24.jar

and

spring-data-jpa-1.6.0.BUILD-20140312.143908-17.jar

Btw, there is no source jar for the Data Commons artifact

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 13, 2014

Oliver Drotbohm commented

Hm, there clearly is… see the repo.

How do you instantiate the repository? If you manually create them via JpaRepositoryFactory you need to call setRepositoryMethodMetadata(…) manually. Is it a CDI context maybe?

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 13, 2014

Jan Goyvaerts commented

Because I have specialized repositories I had to make a repository factory bean - as described in the documentation. I didn't know about the method meta data.

Do you have documentation about what kind of data it expects ?

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

No branches or pull requests

2 participants