spring data jpa multiple dynamic criteria search - spring-data-jpa

I am looking for the best way (or pro/con of different methods) to do a search with multiple dynamic criteria. It means that the number of search criteria might be different.
I have found some method in spring:
MethodNameQuery (fixed number of criteria)
#Query(fixed number of criteria)
Specification
Querydsl
ExampleMatcher
Are there other options that I didn't list?
Which one should I use in spring boot with spring data JPA?
How to perform IN search with ExampleMatcher.
Thanks.

Related

how to generalize greatest-n-per-group within Spring Boot Data Jpa repositories

In the context of a project using spring boot jpa with a lot of "historized" data, I would like to generalize the greatest-n-per-group to get particular data in time range (like the most recent at a given date).
Historical entities implement a special interface with a date range contract (getStartDate() and getEndDate()).
I know how to handle manually this kind of queries (the greatest-n-per-group problem), either with the query generator or with #Query, but but what if I want to generalize this to avoid repeating over and over the same piece of code in my repo ?

Spring data JPA get child collection attributes using projections

I would like to fetch only few attributes from child collection entitites. So, is it possible using Spring JPA projections and Spring JPA repository?
Also, it should not execute multiple queries. Just one query to fetch the selected attributes form child collection.
I want to evaluate options first if it is available in Spring JPA before considering any other alternative.

What is the difference between spring-data-jpa Repository pattern Vs Querydsl query pattern?

I am devloping Spring MVC + spring-data-jpa + Hibernate example. I'm using simple Repository (by extending JpaRepository<T, ID extends Serializable>) pattern to perform querying on DataSource(DS) and get the result. Even I can write any custom query as per my business needs.
While doing research, I find the "querydsl-sql" API. This API uses plugins and need to use QueryDslPredicateExecutor<T> like (by
extending JpaRepository<T, ID extends Serializable>,
QueryDslPredicateExecutor<T>)
. But on high level it look to me that this API also does the same thing that Repository API does.
Could someone please suggest / guide what is the difference between two methods? One use simple Repository and another uses QueryDslPredicateExecutor
List<Customer> findByCustomerNumberAndCustomerId(Integer customerNumber, Integer customerId);
Querydsl method
#Query("select c from Customer c where c.customerNumber=:customerNumber and c.customerId=:customerId")
List<Customer> findByCustomerNumberAndCustomerId(#Param("customerNumber")
Integer customerNumber, #Param("customerId") Integer customerId);
Your Querydsl method example is actually a spring-data repository method.
The difference is that QueryDsl offers a simple and beautiful way to create dynamic queries to database. I.e. it allows to create SQL "on the fly".
This is useful when for example you need to retrieve a collection of entities with a complex filter. E.g. by name, date, cost etc. And resulting SQL should contain only conditions which specified in filter.
Spring data allows to achieve this without Querydsl using built-in Specifications API but Querydsl way is simpler and even more IDE-friendly.
More on this:
https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

How can you determine whether a Spring Data Gemfire query is using a Gemfire index?

I am trying to determine whether all of my Spring Data Gemfire queries are using the indexes defined on the Gemfire server.
With OQL, I know I can add "<trace>" and in the gemfire logs it will show whether an index is being used:
#Query("<trace> SELECT c FROM /customer c, c.emailAddresses email WHERE email.emailAddress = $1")
CustomerEntity findByEmailAddress(String emailAddress);
But what about methods where we don't have OQL defined, like this? (Assuming username is not the key of the Customer region):
CustomerEntity findByUsername(String username);
Great question. Unfortunately, the Repository method for generating GemFire OQL queries based on methods names and conventions used in the name does not support TRACE, or other OQL statements like IMPORT.
As you are probably aware, Spring Data GemFire's Repository support builds on Spring Data Commons Repository infrastructure, which maintains the lowest common denominator for the widest range for data store support (relational, key-value, document, etc).
Still, you can enable debugging for all GemFire OQL queries by setting the GemFire System property...
-Dgemfire.Query.VERBOSE=true
when launching your application. See GemFire's User Guide on Query Debugging for further details.
Unfortunately, this a bit more verbose if you only wanted to TRACE one of your OQL queries, but will accomplish what you want.
The only other way to TRACE in an individual OQL query based on a Repository method is by using the #Query annotation as you illustrated above.
#Query("<trace> SELECT c FROM /customer c, c.emailAddresses email WHERE email.emailAddress = $1")
CustomerEntity findByEmailAddress(String emailAddress);
Your question did give me some ideas though. I am thinking to provide IMPORT and TRACE support via annotations like so...
#Trace
#Import("example.app.domain.CustomerEntity")
CustomerEntity findByUsername(String username);
This would be very elegant and useful.
See the the new JIRA ticket (SGF-392) I filed to add support for this feature.
Thank you!

Set the fetch size with Spring Data

For large result sets, it’s important to increase the fetch size. There have been numerous discussions on how to set the fetch size for Spring’s JdbcTemplate. However, we usually use Spring Data for database access. How can I set the fetch size for a Spring Data query, assuming we use JPA with Hibernate as provider?
It depends on what you want to set. If you want it globally simply add it as a property to your persistence.xml (or what your way of configuration the EntityManagerFactory is). For hibernate that means adding the hibernate.jdbc.fetch_size property.
<property name="hibernate.jdbc.fetch_size" value="50" />
If you want to specify it for certain queries use query hints from JPA on the Query object.
TypedQuery<Foo> q = em.createTypedQuery("some hql here", Foo.class);
q.setHint("org.hibernate.fetchSize", "100");
Or when using Spring Data JPA use a #QueryHints annotation on the interface method. Can be applied to both methods with and without #Query.
#QueryHints(#javax.persistence.QueryHint(name="org.hibernate.fetchSize", value="50"))
List<Foo> findAll();
Links
Hibernate documentation
Spring Data JPA reference | javadoc
JPA 2 Query Hints javadoc
List of query hints for Hibernate