spring data JPA: How to execute aggregate functions - java

I am using Spring Data JPA and I have a requirement where I need to execute the SQL query as below:
select key_1, sum(key_2), sum(key_3) from table_1
where key_1 in ('1', '2') and {dynamic_columns} group by key_1;
For dynamic columns, I am using Spring Data JPA Specifications but I am not sure how can I write the aggregate functions like sum() on multiple columns.

With Spring Data JPA you have a few options in a spring repository.
References:
Baeldung - Spring data JPA
Spring.io - Spring data JPA
Specify a native query
#Query(value="select key_1, sum(key_2) ...", nativeQuery=true)
Optional<Object[]> getAggregates;
Use the providers (HQL for hibernate etc. query language)
#Query(value="select e.key_1, sum(e.key_2) from entity e ...")
Optional<Object[]> getAggregates;
You'll use objects here because you are not returning a specific entity you are adding custom (aggregate) columns. If you were returning a specific entity with a JPA repository you could return that entity instead of Object[]. Each item inside the object array will correspond to a columnof data, if you had multiple rows here you would use:
Optional<List<Object[]>> getAggregates;
Finally, if you have not used optionals before you will get your object array by:
if(objectsOptional.isPresent()) {
Objects[] objects = objectsOptional.get();
...
}
If this isn't what you were looking for i'll need more information to help you out.

Related

Is there a way to dynamically generate Spring Data Jpa queries?

I'm writing an app using Spring Boot, Spring Data. And I'm trying to implement a filtering feature based on different filter parameters.
Using Spring Data queries we can define quite complex logic, e.g.:
#Query("SELECT u FROM User u WHERE u.status = 1")
Collection<User> findAllActiveUsers();
But what if the number of where clauses, order, limit, number of different parameters are unknown till we make an actual filter request which can be quite complex.
Right now filter params are send in a json object which I parse and retrieve them and the result sql query can be something like this:
SELECT * FROM table
WHERE field1 != `value1` and (field1 != ` value2 `OR (field1 = `value3` AND filed2 < 3))
AND field2 != 99
Is it possible to generate dynamically complex queries with undefined (till the actual filter request, during runtime) number of params, where clauses and other stuff?
I use this active project RSQL for JPA
https://github.com/perplexhub/rsql-jpa-specification
Sometime back I wrote an article on Spring Data JPA Query with Dynamic Where Clause. In this example you can send a Where Clause and Map of parameters for that. You can make use of this and modify it a bit suit your needs.
I would suggest using Spring JPA Specification
ref : https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
To build it in a type safe manner, you can use FluentJPA.

Get data through Hibernate without Entity classes

We use Hibernate and annotations to map our db and entities. But for some data tables I don't want entity classes (Because these table names and all are keep changing) so that the application will be more dynamic
So is it possible using hibernate to load data from a table without a entity class?
If so how?
Hibernate provides a way to execute SQL query and to map it to an entity or any class : native sql queries.
Use plain JDBC. I'm not sure what you mean by "table names and all are keep changing" but it sounds like a bad idea to me.
What you could do is create the sql query using string concatenation then use plain JDBC to execute it. That way you can keep table names dynamic.
If Persistence class won't be used, then the data encapsulation won't occur thus data can be accessed directly.
Hibernate Queries interact with the POJO class to fetch data.
Query, Criteria, HQL all the classes use the POJO for fetching data.
Hibernate Framework was mainly designed for the ORM Mapping.
Thus without POJO class, not possible to interact with the database.
Thus using JDBC connection would be the option left.
Use Dynamic models introduced in Hibernate 5 version - 5.4.0.Final
Hibernate Dynamic Models
To achieve this you will need HBM files created.
Session s = openSession();
Transaction tx = s.beginTransaction();
Session s = openSession();
// Create a customer
Map david = new HashMap();
david.put("name", "David");
// Create an organization
Map foobar = new HashMap();
foobar.put("name", "Foobar Inc.");
// Link both
david.put("organization", foobar);
// Save both
s.save("Customer", david);
s.save("Organization", foobar);
tx.commit();
s.close();
Here Customer & Organization are table names
Organization is Parent of Customer.
Click on the above link for more details

Mapping multiple hibernate Entities inside non-entity java bean

Hi I am using a spring boot app with Hibernate using Oracle as DB.
I have 5 classes named
1.Reqest -> Mapped with Request Table
2.Team -> Mapped with Team Table
3.Partner -Mapped with Partner Table
4.Customer -> Mapped with Customer Table
Now I want to Display a Summary of Request on summary screen of the app where all the information from above-mentioned tables is needed.
Suppose I create a bean class as follows.
public class SummaryBean{
Request req;
Team team;
Customer cust;
Partner part;
//Getter setters;
}
Now since I have all the tables mapped with Java classes I can use hql join query to fetch data.
I don't want use plain SQL query with join and then iterate the resulting Object[] list from hibernate query and stub data into SummaryBean manually.
All the above-mentioned tables have REQ_ID as joining column
My question is How can I make hibernate map the result of that query to SummaryBean object?
Is it possible at all?
You can use constructor query.
Something like
"select new SummaryBean(req, team, cust, part) from (here you join your tables)"
You need to provide a constructor for the SummaryBean with those 4 types.
Note that the SummaryBean class doesn't have to be mapped, but you might have to use fully qualified name in the query (packageName.className).

Spring data redis repository doesn't support collection query?

We can do 'findByXXsIn' in spring data JPA, but it seems that I failed to do this in spring data Redis, is there an alternative to do this?
I tagged an object, and store the relation in Redis(tagId,targetId,targetType).
public interface TagRelationRepository {
Page<TagRelation> findTagRelationByTagIdIn(List<String> tagIds,Pageable page);
Page<TagRelation> findTagRelationByTargetType(TagTargetType targetType,Pageable page);
List<TagRelation> findByTargetIdInAndTargetType(List<Long> targetIds,TagTargetType targetType);
}
It's many to many relationship, I want to get the relations by tagIds but just failed.
Currently only simple finder methods with the keywords Is or Equals as well as combinations of those using And / Or are supported.
Please refer to Table 5. Supported keywords in the reference manual for Queries and Query Methods.

Spring Data Jpa Query dsl with fetch join

Is it possible to specify Join Fetch when using QueryDsl and Spring Data Repository?
No, there's no keyword in Spring Data JPA to trigger a fetch.
But you can write a Custom Repository and implement a query using Querydsl there.

Categories