Does Query Dsl support jpa projections? - jpa

It would be good to be able to use projections with Querydsl and JPA
fun findAll(predicate: Predicate): Set<OrderView>
OrderView is a projection of my entity Order.
I can see from the interface this doesn't look possible but is there a future version that supports this or a workaround?

Related

Spring data Dynamic projection without creating projection dto/interface

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.

Spring Data: when use Projection interfaces and DTO projections?

I have this situation:
Spring Data JPA: Work with Pageable but with a specific set of fields of the entity
It about to work with Spring Data and working with a specific set of fields of an #Entity
The two suggestions are totally valid for me:
DTO projections
Projection interfaces
Even more, in spring-data-examples appears both together (I know for sample purposes):
CustomerRepository.java
Thus:
When is mandatory use one over the other and why?
Exists a cost of performance one over the other?
Note in the Class-based Projections (DTOs) section says the following:
Another way of defining projections is by using value type DTOs (Data
Transfer Objects) that hold properties for the fields that are
supposed to be retrieved. These DTO types can be used in exactly the
same way projection interfaces are used, except that no proxying
happens and no nested projections can be applied.
Seems the advantages are: except that no proxying happens and no nested projections can be applied
DTO Approach
Pro
Simple and straigt forward
Con
It will result in more code as you have to create DTO class with constructor and getters/setters (unless you utilize Project Lombok to avoid boilerplate
code for DTOs).
No nested projections can be applied.
Projections
Pro
Less code as it uses only interfaces.
Nested projections can be applied
Dynamic projection allows you write one generic repository method to return
different subset of the attributes in entity object based on client's needs.
Con
Spring generates proxy at runtime
Query could return the entire entity object from database to Spring layer though a trimmed version (via Projection) is returned from Spring layer to client. I wasn't sure about this specific disadvantage, hoping someone to edit this answer if necessary.
If you need nested or dynamic projection, you probably want Projection approach rather than DTO approach.
Refer to official Spring doc for details.
I think that DTO was the first possible solution to work with a small set of data from the Entities. Today, many operations can also be made with projections, but you need to be careful with performance. If you see this Janssen's post Entities or DTOs – When should you use which projection? you will note that DTOs have better performance than projections for reading operations.
If you don't have the problem with performance, projections will be more graceful.

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.

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/

Using the same POJO for a JPA entity and an Elasticsearch document

I have annotated a JPA entity both with #Entity and #Document (from Spring Data Elasticsearch) so I am basically indexing into Elasticsearch the same POJO as JPA.
Is this a good and recommended practice?
If not, what is the alternative? Having two distinct POJOs and mapping the JPA entity to the ES document using something like Dozer?
I think it depends on your use case and the complexity of your object model. For a simple object model, I think that's fine. For a more complex object model, there are a few things to think about:
Do you really want/need to index all of the properties on the entity?
Do you need to transform the object before indexing it? For example, flattening relationships.
Will the serialization to ES cause lazy relationships to be loaded when you don't want them to be loaded?
If not, what is the alternative? Having two distinct POJOs and mapping
the JPA entity to the ES document using something like Dozer?
It looks like Spring Data Elasticsearch is using Jackson for serialization. That's a pretty basic default configuration. If that doesn't work for you and you don't want to introduce a DTO type object, you can always implement your own mapper.