How select one column by predicate in jpa?
For exemple like this
#Query("SELECT SUM (u.sum) from User u")
Double findSums(Predicate predicate);
Spring Data JPA does not have direct support for this kind of query.
Therefore the solution is to fall back to plain JPA in a custom method for your repository.
In that custom method you'd use the Criteria API to create the SELECT SUM (u.sum) from User u apply the predicate to it and execute it using the EnterpriseManager.
Related
I am new to hibernate criteria API. I have written the below query in SQL. How to write it in the Hibernate criteria?
select * from Employee ju, Address ua where
ua.loginname=ju.loginname
and ua.countryname='USA'
and ju.siteprimcontact=1;
Here is a tutorial on the JPA Criteria API that you can use to learn how to write such queries: https://docs.oracle.com/javaee/6/tutorial/doc/gjivm.html
I have a Keyword based JPA query I need to modify in order to exclude records with a particular status. Currently, I have the following:
findAllByLatestVersion_Entity_DataFieldGreaterThanEqualAndLatestVersion_AnotherFieldNull(datefield: Istant, pageable: Pageable)
I do not want to parameterise, therefore I would like to have the query to work as there was a WHERE clause stating that the status IS NOT C, for example. I am struggling to find clear documentation on how to go about. Is it possible to write something along these lines:
findAllByLatestVersion_Entity_DataFieldGreaterThanEqualAndLatestVersion_AnotherFieldNullAndLatestVersion_StatusCNot(datefield: Istant, pageable: Pageable)
Thank you
No this is not possible with query derivation, i.e. the feature you are using here. And even if it were possible you shouldn't do it.
Query derivation is intended for simple queries where the name of the repository method that you would choose anyway perfectly expresses everything one needs to know about the query to generate it.
It is not intended as a replacement for JPQL or SQL.
It should never be used when the resulting method name isn't a good method name.
So just formulate the query as a JPQL query and use a #Query annotation to specify it.
So I have the following model in Django:
class MemberLoyalty(models.Model):
date_time = models.DateField(primary_key=True)
member = models.ForeignKey(Member, models.DO_NOTHING)
loyalty_value = models.IntegerField()
My goal is to have all the tuples grouped by the member with the most recent date. There are many ways to do it, one of them is using a subquery that groups by the member with max date_time and filtering member_loyalty with its results. The working sql for this solution is as follows:
SELECT
*
FROM
member_loyalty
WHERE
(date_time , member_id) IN (SELECT
max(date_time), member_id
FROM
member_loyalty
GROUP BY member_id);
Another way to do this would be by joining with the subquery.
How could i translate this on a django query? I could not find a way to filter with two fields using IN, nor a way to join with a subquery using a specific ON statement.
I've tried:
cls.objects.values('member_id', 'loyalty_value').annotate(latest_date=Max('date_time'))
But it starts grouping by the loyalty_value.
Also tried building the subquery, but cant find how to join it or use it on a filter:
subquery = cls.objects.values('member_id').annotate(max_date=Max('date_time'))
Also, I am using Mysql so I can not make use of the .distinct('param') method.
This is a typical greatest-per-group query. Stack-overflow even has a tag for it.
I believe the most efficient way to do it with the recent versions of Django is via a window query. Something along the lines should do the trick.
MemberLoyalty.objects.all().annotate(my_max=Window(
expression=Max('date_time'),
partition_by=F('member')
)).filter(my_max=F('date_time'))
Update: This actually won't work, because Window annotations are not filterable. I think in order to filter on window annotation you need to wrap it inside a Subquery, but with Subquery you are actually not obligated to use a Window function, there is another way to do it, which is my next example.
If either MySQL or Django does not support window queries, then a Subquery comes into play.
MemberLoyalty.objects.filter(
date_time=Subquery(
(MemberLoyalty.objects
.filter(member=OuterRef('member'))
.values('member')
.annotate(max_date=Max('date_time'))
.values('max_date')[:1]
)
)
)
If event Subqueries are not available (pre Django 1.11) then this should also work:
MemberLoyalty.objects.annotate(
max_date=Max('member__memberloyalty_set__date_time')
).filter(max_date=F('date_time'))
One way of conducting an SQL query is the defined NamedQuery in JPA:
Query query = entityManager.createNamedQuery("Users.findByName");
An alternative to this is running it without defining a NamedQuery:
Query query = entityManager.createQuery("SELECT SELECT u FROM Users u");
From what i see, NamedQuery is favorable for it is defined at one-place-for-all in the entity class and is available to a pojo that has a use for it without getting into SQL.
Are there any differences between the two?
The only difference is that one is a String that only can be used in the class where is declared, the one of your second example
Query query = entityManager.createQuery(" SELECT u FROM Users u");
The NamedQueries can be used in different DAO without need to define them again, just call and PersistenceProvider will find them using #NamedQueries - #NamedQuery, or xml files when you define them.
Basically a named queries are a powerful tool for organizing query
definition and improving application performance.
Also a good important stuff is that some provider processed the JPQL inside the namedqueries at the startup time, this gives a hit on the performance, in the second case that you set in yout question, persistence provider is not aware of the query existence and does not have the chance to process it on startup and need to run the process when is required.
Does Spring have any features which allow for a batch select? I basically have n number of selects to execute depending on the number of records in a list. At the moment because the size of the list is always changing i have to dynamically build the SQL which will be executed. The end product looks something like this
select * from record_details t WHERE id IN ((?),(?),(?))
However the code to generate this SQL on the fly is messy and I'm wondering if there is a nicer approach for this type of problem?
The NamedParameterJdbcTemplate (and according support class) does have that support.
public void someRepoMethod(List ids) {
String query = "select * from record_details where id in (:ids)";
getNamedParameterJdbcTemplate().query(query, Collections.singletonMap("ids", ids), new YourRowMapper());
}
If you don't want to generate SQL yourself you have to use some existing framework. From what i know myBatis, is more lightweight than hibernate so it can suit you more, but there may be other more suitable.