I came to know there is a feature in JPA, which fetches only those properties of entity which we need, and it is called a projection query.
Most Datastore queries return whole entities as their results, but often an application is actually interested in only a few of the entity's properties. Projection queries allow you to query the Datastore for just those specific properties of an entity that you actually need, at lower latency and cost than retrieving the entire entity.
I am looking for an implementation of the projection queries, but it seems like there are lesser resources about this.
I have a table USER with 50 columns. I need to retrieve only 5 columns from this table as a list of entities. This is to show it in a JSF data table.
How can I achieve this with projection query? Or is there a better alternative to this?
select u.id, u.name, u.birthDate from User u
This will return a List<Object[]>. Each Object[] in the list will contain a user ID, a user name and a user birth date.
You execute it just like a regular query:
Query q = em.createQuery(jpql);
List<Object[]> users = q.getResultList();
Related
I am trying to paginate results with the JPA criteria API. After looking through this answer: Total row count for pagination using JPA Criteria API
I see that the way to do it is to make a separate query that counts the number of rows returned by that specific criteria query. (They do this by making an array of predicates and using the same list for both the count query and the actual paginated query).
However, my criteria query cannot be replicated by a simple predicate list because it involves many joins with other tables and predicates involving comparisons with results returned from sub-queries.
I was wondering if there is a convenient way to get the row count for a particular criteria query without duplicating the query. (Or if there is an easy way to obtain a deep copy of a criteria query by passing in a reference)
Thanks in advance!
The "convenient way" to do this is to resort to native SQL and use window functions. You can easily add a window function to your top level SELECT that simply counts all the rows as follows:
SELECT x, y, ..., COUNT(*) OVER()
FROM ...
By using SQL instead of JPQL / Criteria API, you'll have access to a variety of other very useful features, like the above.
I have a MariaDB database with 2 schemas : Store1 and Store2. These schemas contain several tables. "Products" is one of these.
In my repository, I need to add the following request :
#Query("SELECT Store1.Products.Id, Store1.Products.Label FROM Store1.Products UNION SELECT Store2.Products.Id, Store2.Products.Label FROM Store2.Products")
public Page<Products> getAllProducts(Pageable pageable);
Of course, the query doesn't work, it's just for an example about what I want to do.
I've briefly read about multi-tenancy, but I don't know if it fits my use case, and seems complex for such a simple case.
Is there a simpler way to get this query ?
I have a User object with an addresses set to Address. Now let's say I need to fetch 1,000,000 users and display their address in some report.
The Hibernate way to do it is to create one sql call to the User table, and then another call to the Address table for each user. The result is a grand total of 1,000,001 calls and a long query time.
On the other hand if you aggregate all the foreign keys (for example User_Id) and run an IN sql call
FROM Address where User_Id IN (,,,,,,,,)
you reduce the number of calls to 2 - one to the User table and one to the Address table, to bring all the 1,000,000 required address in one call.
But this requires some work on the app side. Not a lot of work, just a for loop, but still. Is it possible to ask Hibernate to do it the efficient way?
Please note that LAZY fetching has nothing to do with it. For my use case I need an EAGER fetching.
Hibernate will generate single query using JOINS. I dont know what sort of configuration you are using whatsoever.SELECT u FROM User u LEFT JOIN FETCH u.address would give u address via joins. Single query
I would suggest you make 2 queries. I use Java 8 stream.
Query query = session.createQuery("from User").setMaxResult(BATCH);
List<User> users = query.list();
final List<Integer> userIds = users.stream()
.map(u -> u.getUserId()).collect(Collectors.toList());
query = session.createQuery("FROM Address where User_Id IN (:ids)").setListParametrs(userIds);
final List<Address> result = query.list();
Also I would like to suggest do not get 1,000,000 rows in 1 query, use batch processing.
I am stuck with an issue. I have 3 tables that are associated with a table in one to many relationship.
An employee may have one or more degrees.
An employee may have one or more departments in past
An employee may have one or more Jobs
I am trying to fetch results using named query in a way that I fetch all the results from Degree table and Department table, but only 5 results from Jobs table. Because I want to apply pagination on Jobs table.
But, all these entities are in User tables as a set. Secondly, I don't want to change mapping file because of other usages of same files and due to some architectural restrictions.
Else in case of mapping I could use BatchSize annotation in mapping file, which I am not willing to do.
The best approach is to write three queries:
userRepository.getDegrees(userId);
userRepository.getDepartments(userId);
userRepository.getJobs(userId, pageIndex);
Spring Data is very useful for pagination, as well as simplifying your data access code.
Hibernate cannot fetch multiple Lists in a single query, and even for Sets, you don't want to run a Cartesian Product. So use queries instead of a single JPQL query.
I'm trying to write a simple query in hibernate where I just get a descending list of users with the most points. Basically I'm trying to write this query select user_id from user_points group by user_id order by sum(points) desc. This works on the Postgres db I'm working on.
I have the following HSQL query select c.user from UserPoints c group by c.user order by sum(c.points) desc. The Points table has a column called user_id which refers to the user table. In our mapping user_id is mapped to a User class.
However when I run this query I get column "user1_.user_id" must appear in the GROUP BY clause or be used in an aggregate function. I tried searching for similar issues but only really came up with this: JPA Query/Hibernate: Column must appear in the GROUP BY clause or be used in an aggregate function which is unanswered.
I'm kind of stuck with HQL because the other thing I need to do is join on a table that doesn't have a mapped association (but also has a user_id key). I'm also trying to keep this query as fast as possible. Any help would be really appreciated as I'm really confused as to why this isn't working.
So I think I may have found what the issue was. We actually have two mappings to the user_id column. One is a property where we have the user_id as just a regular long and the other many to one mapping where we map it to the user class. I set the logging level to debug so I can see the query that hibernate was creating and it seems like it was using turning the select c.user to all the columns in the user table (which means it was using the many to one mapping correctly), but for some reason in the group by clause it was converting c.user to the user_id property. Since I can't change the mapping and I'm on a tight deadline I've opted to just write a regular SQL query to grab the user ids and then run another criteria query to get all the users in that list of ids.