Using referencing class field as filter in Spring Data Repository - spring

Context: I have three models, Owner, Property and Community. Property has a reference to its Owner, and another one to the Community.
I need to make the following query: find all the owners in a community which meet some criteria (floor number, property letter, etc, all the fields of the criteria are inside the Property class)
Is there any way to implement this in a repository without creating a bidirectional relationship or writing a native query? Something like:
Set<Owners> findAllByCommunityAndProperty_floorNumberAndProperty_letter(Community community, Property property);
(I would need a bidirectional relationship to make the query above)

You can use a query like this
SELECT o
FROM Property p
INNER JOIN property.owners o
WHERE p. ...
See http://www.objectdb.com/java/jpa/query/jpql/from#INNER_JOIN_ for various examples of join syntax.
In Spring Data JPA you will probably use the #Query annotation to bind that query to a method.

Related

Spring JPA Derived query method groupBy

Hi I was building an app and was wondering on how I can convert this query into a derived query method without using the annotation #Query:
SELECT address, COUNT(*) address FROM `employee` GROUP BY address ORDER BY address DESC LIMIT 5
I have tried it here is how I did it
List<Employee> countByAddressGroupByAddressByOrderByAddressDescLimit5();
This throws the following error
Invalid derived query! No property groupByAddressBy found for type String! Traversed path: Employee.address.
I was wondering if what am I doing wrong here thank you in advance.
I don't think query derivation supports group by.
You can't.
Derived queries don't support GROUP BY.
Derived queries are intended only for simple queries, where the mapping between a normal method name that you might choose independently from Spring Data and the query needed for implementation is obvious.
For more complex cases like the one you describe other mechanisms are available, like annotated or named queries. Nobody wants to use a method name like countByAddressGroupByAddressByOrderByAddressDescLimit5 anyway.
As others said, derived queries do not support this. There might be other reasons besides simply not being a 'practical' solution.
AFAIK derived query methods are restricted to retrieving instances just for the entity type managed by the repository (you can retrieve MyEntity, Optional<MyEntity>, Collection<MyEntity>, etcetera) or projections that match the fields/columns used for the managed entity.
When you use 'Group By', you break with this resultset structure, you usually have to explicitly indicate which columns you want to retrieve or which operations you want to perform on the grouped columns (which would be impossible using just a method name).
TL;DR
You can't easily indicate the columns you want to include in a 'Grouped By' query result, so no, I don't think there is a way to use this technique with 'Group By'.

Run complex SQL Query with spring boot repositories

i have a little complex scenario using spring data and jpa currently.
My data structure is like:
And i like to create a filter: give me all events which belongs to a list of structures, within a given period and is assigned to a list of categories.
I was able to create a sample SQL statement:
select * from event e inner join period p on e.period_id=p.id
inner join category_item_ids ci on e.id=ci.item_ids
inner join category c on ci.category_id=c.id
inner join event_assignment_structure_ids es on es.event_assignment_id=e.id
where p.start between '2020-05-01 12:00:00.000000' and '2020-11-14 12:00:00.000000' and
c.id in (1) and
es.structure_ids in (1,2)
But my objects are currently not wired together by all the JPA annotations.
e.g. the "Same ID" is something i did by convention to make the parts a little more independend.
So using the JPA way is currently no option i guess due to the missing relations.
Introducing them will be also quite a lot of work.
So i was wondering if there is a possiblity to run the sql query directly (i could use native query, but thats also no option, cause the filter values are not always given, so i need 13 native queries)
I used enityManager and query Builder in the past, but thats also no option due to the missing jpa relations.
Any ideas are much welcome :-)
Regards
Oliver

Querying multiple tables using jpa repository

Suppose if I have 3 entities - User, Skills, Department
and I have repositories corresponding to all of them - UserRepository, SkillRepository, DepartmentRepository.
I understand that the relation mapping between entities i.e. one-one many-many should be specified in the respective entity classes. The question is I want to use all of the 3 entities in a query. How would I do it? A single repository is associated with only one entity right? So, how/where would I write it?
As there are many different ways to specify queries with Spring Data JPA there are various answers to this.
Maybe you don't have to. If entity A references B and you just want to get the Bs with your A you simply use your ARepository to load As and use object navigation to get your Bs. You might read up on eager and lazy loading for more information about how to control this.
If you want referenced entities in the where condition you can use property paths in your query method names: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
If you are using #Query annotations you can do (almost) whatever you want with JPQL. Among others, you may as well navigate properties to use them in where clauses.
In general, you'd put that query in the matching repository based on the primary entity returned.

Spring JPA custom query with combination of parameters in WHERE condition?

How to write JPA query in Spring Data that uses at least one of three parameters?
I have these three parameters:
Id (PK)
Name
Surname
Client must supply at least one of these three parameters and I want to find user by these not-empty parameters.
Is it possible to create such custom query to my repository or do I have to create custom queries for all possible combination of WHERE conditions?
You can have your repository extend org.springframework.data.querydsl.QueryDslPredicateExecutor and use the inherited findAll(Predicate predicate) method to query using any combination of parameters.
You would not then have to write any query methods:
http://docs.spring.io/spring-data/jpa/docs/1.10.5.RELEASE/reference/html/#core.extensions.querydsl
You can also have the Predicate automatically bound in a Spring MVC Controller as detailed here:
https://spring.io/blog/2015/09/04/what-s-new-in-spring-data-release-gosling#querydsl-web-support
and here:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#core.web.type-safe
So your controller can then automatically handle a search with 1,2 or all 3 parameters passed as request parameters without your having to write any code at all.
This is where you need the ability to create dynamic queries at runtime.
In your application code, you should have logic to build the predicate based on whether each of the above properties from the input DTO is empty or not.
One way to do it is to use QueryDSL.
To use QueryDSL, you should include the relevant dependency in your pom/gradle file and then your repository should extend the QueryDslPredicateExecutor interface. This will give you two additional generic finder methods.
T findAll(Predicate) or
Page<T> findAll(Predicate, Pageable)
One thing to keep in mind is that the above two methods are appropriate where this is no need to do a join
Your requirement here seems to be a single table query, so either one of the finder methods should suffice.
If you do need to do a join with other tables and need fine grained control over how the JOIN happens (INNER JOIN vs LEFT OUTER JOIN vs CROSS JOIN) etc, then you should consider creating a Custom repository that your repository can extend.
And then provide your own customImpl that you can now access from the repository.
thanks a lot for the reply ... as i read Spring is not easy flexible as other framework... for i.e i tried some node js api framework and it is easier and more flexible .. what do you think about this ?

nhibernate table pr hierarchy fetching specific class with LINQ

I have a class hierarchy mapped into one table. There is one superclass and 8 different sub classes. A lot of my queries needs to fetch e.g. 2 of the sub classes only for a specific date.
The table has a discriminator column that nhibernate itself uses. But when using LINQ for querying it is not possible to use this discriminator as there is no property for it.
Is there a commonly used trick for only fetching specific sub class when using nhibernate ?
For now I first have Linq 4 Nhiberneate query that fetches all sub classes into a given period. And then uses Linq 4 objects to filter on the sub classes that I need.
Is it possible to expose the discriminator column of the table as a property and thereby be able to make a where clause on it ?
In Hql querying subclasses is done by class, so you'd do
from subclass
where subclass.DateTime = :myDateTime
The docs also say you can query hierarchies by the special class property, eg:
from Eg.Cat cat where cat.class = Eg.DomesticCat
I don't know if this is possible with the Criteria API or NH Linq Provider.
You could always get all the instances with the correct time, and then filter client side, eg:
var allCandidates = from super in session.Linq<SuperClass>()
where super.Date > DateTime.Now.AddDays(-1)
select super
var results = from candidate in allCandidates
where candidate.GetType() == typeof(SubClass)
select candidate
It's a bit nasty, and if the subset of classes you're querying is always the same, you might be better off inserting another class in the hierarchy and querying that.

Resources