I am using spring boot JPA specifications for executing complex queries. However, the table I am querying contains more than 20 columns and I need to pull just 3. I tried cq.multiselect(...) but it didn't work and returned me the entity with all the columns.
On investigation, I got to know that it's a bug with specifications that's not yet fixed. Another option was to use projections but specifications can't be combined with projections. An attempt to do so returns the complete entity.
I do not want to switch to Querydsl or #Query approach since it's an existing code and I am stuck with specifications. Any pointers on how to limit the number of columns will be much appreciated :)
Got to know Spring boot JPA Specifications doesn't provide any way to limit the number of columns. There is a bug related to this feature and it's pending for more than 3 years now. Not sure if it will be available soon
Use QueryDslPredicateExecutor.findAll(Predicate predicate, Pageable
pageable) and then get the actual results back using PageRequest.of(0,
limit).
Querydsl limit record example
Related
Context:
So i'm writing a RestAPI using Spring boot. I have a very bulky endpoint, which makes a decent amount of queries. The database itself is big, averaging 10 mil rows per table (some hold 1k, one holds 100 mil, most hold 5mil-30mil). First query returns list of string Id's. From that point on we do more operations using these ID's.
General Problem:
In some cases the endpoint is asked for a lot of these entities (1000 or 2000). Once we get them, we don't want to do the following queries using an IN clause, since that would be slow for that many id's. Fortunately Postgresql provides the JOIN VALUES expression, which makes the queries extremely fast, but it's syntax (more like the parameter binding) is unfamiliar to hibernate.
Syntax: https://www.postgresql.org/docs/10/queries-values.html
Specific problem : Passing in a List entityId's in hibernate, makes it do
entityId, entityId, entityId ...
For a values expression, we need it to do:
(entityId), (entityId), (entityId) ...
Question: What would be the best approach to do this? Add this custom binding for parameters? If that is the best approach, how would i go about doing that?
Thank you for any ideas/suggestions in advance!
Looking at the following code:
mongoOps.getCollection("FooBar")
.distinct("_id", query(where("foo").is("bar")).limit(10).getQueryObject());
I would expect this to return only the first 10 distinct _ids of collection FooBar.
But unfortunately, running this against a Collection having more than 10 documents matching the criteria, it returns all of them ignoring the limit(10) specified here.
_id is an ObjectId.
How can I achieve this?
Is it a bug in Spring Data?
I'm already aware how I can achieve this using an aggregate but I'm trying to simplify the code if possible since using an aggregate takes many more lines of code.
FYI: I'm using Spring Data Mongodb 1.10.10 and unfortunately, updating is currently not an option.
I have inherited a groovy code base (that among other things) uses Hibernate as an ORM as part of Dropwizard and I've in the process of updating the dependencies I start seeing the following warnings.
org.hibernate.orm.deprecation: HHH90000022: Hibernate's legacy org.hibernate.Criteria API is deprecated; use the JPA javax.persistence.criteria.CriteriaQuery instead
As an experiment I tried updating one of the queries to use the new CriteriaQuery API. However pretty quickly I ran into an issue, the old code uses setMaxResults(). I assume under the hood this is using the LIMIT to limit the number of results.
How to I limit the results of a CriteriaQuery to 1?
A related question, how do I do pagination with CriteriaQuery?
I tried reading through the Hibernate 5.3 users guide, (especially chapter 16 the the new API) searing for "limits" and "max results" and such and all the talk I could find was in the "Legacy Hibernate Criteria Queries".
I'd be happy to provide some example code if it helps, but you could just use the example from the manual (Example 534. Selecting an attribute) and show how to enhance it by limiting the results.
Define setFirstResult() and setMaxResults() on the Query like this (offset=0 and limit=10):
sessionFactory.getCurrentSession().createQuery(criteriaQuery).setFirstResult(0).setMaxResults(10).getResultList());
To paginate you just have to set the first and max (assuming you're passing in a Pageable Object:
criteria.setFirstResult(pageable.gotOffset());
criteria.setMaxResults(pageable.getPageSize());
Also, to limit, just call:
Criteria queryCriteria = session.createCriteria(MonthlySubscriber.class);
queryCriteria.setFirstResult(0);
queryCriteria.setMaxResults(1);
monthlySubscriberList = queryCriteria .list();
I have a query which has 2 'in' Clauses. First in clause takes around 125 values and second in clause of query takes around 21000 values. Its implemented using JPA CriteriaBuilder.
Query itself executes very fast and return results within seconds. Only problem is entityManager.createQuery(CriteriaQuery) takes around 12-13 minutes to return.
I search all over SO, all the threads are related to performance of Query.getResultList. None of them discuss about performance of entityManager.createQuery(CriteriaQuery). If you have seen such behavior earlier, please let me know, how to resolve it.
My JDK version is 1.7. Dependency version of javaee-api is 6.0. Application is deployed on JBOSS EAP 6.4. But that's not the concern as of now, as I am testing my code using junit using EntityManager connected to actual Oracle database. If you require more information, kindly let me know.
A hybrid approach is to dynamically create a query and then save it as a named query in the entity manager factory.
At that point it becomes just like any other named query that may have been declared statically in metadata. While this may seem like a good compromise, it turns out to be useful in only a few specific cases. The main advantage it offers is if there are queries that are not known until runtime, but then reissued repeatedly. Once the dynamic query becomes a named query it will only bear the cost of processing once.
It is implementation-specific whether that cost is paid when the query is registered as a named query, or deferred until the first time it is executed.
A dynamic query can be turned into a named query by using the
EntityManagerFactory addNamedQuery()
Keep us informed by the result and good luck
I observed that, having single query with 21 IN clauses (each with 1000 expressions) and all combined with OR clauses, made query run slower. I tried another approach of executing every IN Clause as a part of separate query. So these 21 individual queries performed better overall.
Another issue I observed was that Query with CriteriaBuilder was slow when result set is huge (something like 20K rows in result set). I solved this issue by adding query hint to my typed query:
TypedQuery.setHint("org.hibernate.fetchSize", 5000);
Hope it will help others.
Code in Hibernate is not expected to be used for binding lots of params:
for ( ImplicitParameterBinding implicitParameterBinding : parameterMetadata.implicitParameterBindings() ) {
implicitParameterBinding.bind( jpaqlQuery );
}
Unfortunately you need to find different approach if you want to do something similar.
We are using Hibernate with IBM DB2 9.7. The database gives error about Hibernate generated too large select statement list (including a lot of joins). The error code is 840. Can something be done to fix this? I know the generated select list is very long, but can Hibernate be set to split it into parts or something?
Edit: I reopened this since the problem seems to be a bit larger. So there is a JIRA issue (now rejected) at https://hibernate.onjira.com/browse/ANN-140.
So the problem is that with Hibernate Annotations, it is not possible to add discriminator with Join strategy. XML configuration however does support this.
Pavel nicely states the problem in the above link discussion like this:
"It would be nice to see how the problem with the multiple joins is faced when the
underlying DB has restriction on the number of joins one can execute in a single SQL?
For instance MySQL seems to allow only 31 joins. What happens if the class hierarchy
has more than 31 sub-classes?"
An the above is the very problem I am having. We are using annotations and the subclasses are quite a few, creating massive amounts of joins, breaking the DB2 statement.
Any comments on this? I could not find a direct solution either.
Hibernate has few fetching strategies to optimize the Hibernate generated select statement, so that it can be as efficient as possible. The fetching strategy is declared in the mapping relationship to define how Hibernate fetch its related collections and entities.
Fetching Strategies
There are four fetching strategies
fetch-”join” = Disable the lazy loading, always load all the collections and entities.
fetch-”select” (default) = Lazy load all the collections and entities.
batch-size=”N” = Fetching up to ‘N’ collections or entities, Not record.
fetch-”subselect” = Group its collection into a sub select statement.
For detail explanation, you can check on the Hibernate documentation.