Spring data Dynamic projection without creating projection dto/interface - spring-data-jpa

I use Spring data by extending SimpleJpaRepository, Sometimes we need only a few special fields of an entity on sometimes other fields. if we create a projection class or interface for every need, there will be many classes that are used only for one application. is there any way to pass fields/columns as map/list to createQuery ?

I use Spring data by extending SimpleJpaRepository
That is at least weird, if not wrong. you'd normally extend on or multiple of Spring Data interfaces.
Anyway, yes this is possible like so:
Is there a way to achieve this?
Yes, there is.
Version 2.6 RC1 of Spring Data JPA introduced fluent APIs for Query By Example, Specifications, and Querydsl.
This you can use among other things to configure projections. Note that only interface projections are supported.
You can use projections like this:
interface SomeRepository extends CrudRepository, JpaSpecificationExecutor{}
MyService {
#Autowired
SomeRepository repository;
void doSomething(){
List<User> users = repository.findBy(
someSpecification,
q -> q.project("firstname", "roles").all()
);
// ...
}
}
It will return an entity, but only the fields given in the project clause will be filled.

Related

Deciding which collection

I have an abstract class which is extended by large number of other POJOs, I need all these main POJOs to be stored in a dedicated collection.
My repository looks like this:
interface TimesliceRepository extends MongoRepository<AbstractTimeslice, String>
How can I make it so that objects are directed to the appropriate collection? Eg: AATimeslice, BBTimeslice, etc...
Or do I have to have a repository for every POJO?
Also, would read queries work? How would I be able to query for BBTimeslice only?
After some research, I came to the conclusion that for my uses cases its better to use MongoTemplate and not MongoRepository.

Custom operator support in naming convention

as we know, spring-data-jpa supports repositories that generate queries based on function names, i.e (kotlin):
#Repository
interface LocationRepository : JpaRepository<DbLocation, UUID>,
JpaSpecificationExecutor<DbLocation>{
fun findOneByNameIgnoringCase(name: String)
}
Now, postgres supports some custom operators, for example timerange '#>' timestamp (read: timerange contains timestamp).
I'd like to have a function like this, without resorting to native queries/specifications:
#Repository
interface LocationRepository : JpaRepository<DbLocation, UUID>,
JpaSpecificationExecutor<DbLocation>{
fun findOneBySomeFieldContainsTimestamp(something: Instant)
}
Is there any way to extend spring data jpa to also support new operators?
Thanks in advance.
Is there any way to extend Spring Data JPA to also support new operators?
Not really.
Of course, technically the answer is yes since Spring Data is Open Source and you can fork it. A good starting point would be JpaQueryCreator.build() which contains a switch statement for all the supported operators.

Spring data repository and DAO Java Generics

Reading about using Java Generics in DAO layer, I have a doubt applying this in spring data repositories. I mean, with spring data repositories, you have something like this:
public interface OrderRepository extends CrudRepository<Order,OrderPK>{
}
But if I have other 10 entities, I have to create 10 interfaces like the one above to execute CRUD operations and so on and I think this is not very scalable. Java Generics and DAO is about creating one interface and one implementation and reuse this for entities but with Spring Data repositories I have to create one interface for each entity so ...
You didn't really state a question, so I just add
Is this really true? And if so, why?
and answer it:
Yes, this is (almost) correct. Almost, because you should not create one repository per entity, but one repository per Aggregate Root. See http://static.olivergierke.de/lectures/ddd-and-spring/
Spring Data Repositories offer various features for which Spring Data needs to know, what entity it is dealing with. For example query methods need to know the properties of the entity, in order to convert the method name to JPA based query. So you have to pass in the information to Spring Data at some point and you also have to pass in the information, which entities should be considered Aggregate Roots. The way you do that, is by specifying the interface.
Do you really need that? Well if all you want is generic Crud functionality, you can get that straight out of the box with JPA. But if you want query methods, Pagination, simple native queries and much more Spring Data is a nice way to avoid lots of boiler-plate code.
(Please keep in mind that I'm biased)

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/

JpaRepository vs CRUDRepository findAll

I have a simple question: why JpaRepository is returning List of entities but CrudRepository returns Iterable of entities?
Is it done on purpose? I guess it's because CrudRepository is more generic interface and there may be some specific repository which returns Iterable.
It makes harder to use CrudRepository without using specific JpaRepository..
Thanks
The class CrudRepository is part of the Spring Data Commons project and is the recommended interface to extend regardless of the actual data store used.
The reason CrudRepository methods return Iterable and not List (or Set) is because some data stores allow streaming of results and using a Collection type would result in loss of functionality for such stores.
JpaRepository extends PagingAndSortingRepository
and PagingAndSortingRepository extends CrudRepository.
This allows JpaRepository to have a more specific return type of Itrable which is List