I have a java spring boot application that use hibernate as ORM. The database is an Azure SQL Server.
I've enabled the setShowSql on vendor adapter configuration.
When I want to find objects, I used the TypedQuery's methods setFirstResult and setMaxResults and than invoke the getResultList method.
The query printed in the console doesn't contains the OFFSET and ROW FETCH clauses and it seems that Hibernate first retrieve all result and than apply the pagination on the resulted list.
This obviously causes performance issues.
Where am I doing wrong?
Below I report the sample code I used.
query.setFirstResult(pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
...
query.getResultList()
The only time Hibernate will explicitly include the OFFSET and FETCH clauses under a SQL Server dialect will be when the following conditions are met:
You must use org.hibernate.dialect.SQLServer2012Dialect or any future 2012+ version.
Your query must include an ORDER BY clause.
Your query is not executing a TOP clause query.
The SQLServer2012Dialect uses a customized LimitHandler implementation called SQLServer2012LimitHandler that you can see here that explicitly handles this use case or otherwise falls back to the old behavior.
If both of the requirements above are being met but the logic is still fallig back to the old behavior for some reason, then it's a bug. In that case, you probably should update HHH-12152 with a test case so we can fix it.
Related
I want to learn more about Spring JPA and what happens under the hood when a native JPA query (using PostgreSQL) is defined and called in a Repository class. I have tried searching online but all posts are related to defining and using native queries.
I am more interested to learn about what happens when my SpringBoot application calls a method that is annotated with #Query. I am mainly looking into this to try and understand the performance of executing such a query within Java.
Can anyone point me to a resource which goes in depth on what exactly happens under the hood when using Spring JPA?
Can anyone point me to a resource which goes in depth on what exactly happens under the hood when using Spring [DATA] JPA?
The authoritative source for this kind of information is the source.
Let me point you to some places of interest.
Basically the following happens:
find and extract the query from the annotation.
possibly create a count query from that.
replace spell expression with parameters.
add ordering if applicable.
prepare the query with the EntityManager.
register parameters.
add pagination limits.
execute the query.
transform result.
Output log to view what SQL query really generated and executed
For example, in application.properties:
logging.level.org.springframework.data.jpa=debug
logging.level.org.hibernate=debug
SpringBoot log reference
Check the source code of spring-data-jpa here:
https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java
We need to cache the results of a query; the query returns the whole table of a database. The problem is that the database is changed externally by other application; the Java application making the query is notified with the exact primary key of the row changed.
Is it possible to replace only the changed element from the query cache, not the whole list?
Is this the 1st level cache (from EntityManager) 2nd level Cache (from EntityManagerFactory) or a different cache?
If it is possible can this be done from JPA?
entityManager.refersh(entity);
or is this query cache the 2nd level JPA cache:
entityManagerFactory.getCache().evict(cls, primaryKey);
or only possible through Hibernate/EclipseLink API?
If is not possible, in order to achieve this, would calling entityManager.find() on all elements do it?
I haven't find anything useful neither in Hibernate documentation nor in EclipseLink documentation. Hibernate supports regions and refreshing only regions, but we need entity-level refresh granularity.
Later edit to clarify my findings.
Following the link posted by #Chris in the comment I have found out that what I wanted is actually supported by EclipseLink but only for Oracle Database (there is possible to implement own handler for other vendors; but the call from database is not standardized and differs from vendor to vendor). I have not found if Hibernate supports this or not.
Anyhow the query cache from EclipseLink had some very poor performance compared with Spring Cache (based on CocurrentMap) or with custom based cache so will remain with Spring Cache or Custom Cache over Spring Jdbc.
EntityManager.refresh() is what you want - it refreshes the entity from what is in the database. This should also update the entity in the shared cache if you are not in a transaction, otherwise you may need to use the entityManagerFactory.getCache().evict(cls, primaryKey); as well to clear the second level shared cache so it can be read into it as well later on.
For glassfish v2, I have searched through the web and I cannot find anyway to specify query timeout when using TopLink essential query hint. We have another option to migrate to EclipseLink but that is not feasible.
have tried the solution in
http://forums.oracle.com/forums/thread.jspa?threadID=974732&tstart=-1
but it seems the DatabaseQuery which one could set a timeout value is actually for Toplink, not TopLink essential.
Do we have some other way to instruct the JDBC driver for this timeout value other than the query hint? I need to do it on query-basis and not system-basis (which is just to change the value of DISTRIBUTED_LOCK_TIMEOUT)
According to the documentation of Toplink JPA about Query Hints:
You can use the following TopLink JPA
hints (for more details on these
settings please refer to the TopLink
documentation)
fetchSize Takes an Integer. Allows
the user to set the fetchSize of a
TopLink query.
referenceClass Takes
a class. Override the target class of
the query.
cacheUsage Takes an
Integer. Describes how TopLink makes
use of the cache for querying objects.
refresh Takes a Boolean. Set to true if the cache should be refreshed from
the database.
lockMode Takes an
Integer. Set for Pessimistic Locking.
expression Takes a TopLink Expression object. Used for querying
using TopLink API.
timeout Takes an
Integer. Sets the the query timeout in
milseconds.
So my understanding is that you should be able to do that:
Query queryEmployeesByFirstName = em.createNamedQuery("findAllEmployeesByFirstName");
queryEmployeesByFirstName.setHint("timeout", new Integer(5000));
Not tested though.
I'm using Spring's JDBC support to run SQL queries and updates on an Oracle database. I'd like to insert a row and then get the key that it was assigned (using an Oracle sequence). In normal JDBC code, I would include a RETURNING INTO clause and then register an output parameter (well described here)
However, I would like to just use Spring to handle all my JDBC work for me. For non-insert SQL statements, I'm currently using a MapSqlParameterSource object and registering all my input parameters. Can I also register an output parameter like this and have it returned to me? I looked over the Chapter 11 portion of the Spring docs, and I saw there was support for an output parameter if I'm using stored procedures, but I would like to avoid doing that if possible. Thanks.
I don't think the Spring JDBC support API provides explicit support for OUT parameters, so you may need to step back a bit and use the more general query API provided by JdbcTemplate:
Object execute(PreparedStatementCreator psc, PreparedStatementCallback action)
This lets you perform arbitrary JDBC operations within the scope of a Spring-managed connection and PrepatedStatement. The downside is that the handling and tidyup of things like ResultSets becomes your problem.
Check out this code - it may do what you want, not sure if Oracle supports this syntax though.
getReturnedGeneratedKeys() Spring JDBC Excample
I'm currently experimenting with EJB3 as a prestudy for a major project at work. One of the things I'm looking into is query caching.
I've made a very simple domain model with JPA annotations, a #Local business interface and a #Stateless implementation in an EJB-JAR, deployed in an EAR together with a very simple webapp to do some basic testing. The EAR is deployed in JBoss 5.0.1 default config with no modifications. This was very straighforward, and worked as expected.
However, my latest test involved query caching, and I got some strange results:
I have a domain class that only maps an ID and a String value, and have created about 10000 rows in that particular table
In the business bean, there's a very simple query, SELECT m FROM MyClass m
With no cache, this executes in about 400ms on average
With query cache enabled (through hints on the query), the first execution of course takes a little longer, about 1200ms. The next executions take 3500ms on average!
This puzzled me, so I enabled Hibernate's show_sql to look at the log. Uncached, and on the first execution with cache enabled, there is one SELECT logged, as expected. When I should get cache hits, Hibernate logs one SELECT for each row in the database table.
That would certainly explain the slow execution time, but can anyone tell me why this happens?
The way that the query cache works is that it only caches the ID's of the objects returned by the query. So, your initial SELECT statement might return all the objects, and Hibernate will give them back to you and remember the ID's.
The next time you issue the query, however, Hibernate goes through the list of ID's and realizes it needs to materialize the actual data. So it goes back to the database to get the rest. And it does one SELECT per row, which is exactly what you are seeing.
Now, before you think, "this feature is obviously broken", the reason it works this way is that the Query Cache is designed to work in concert with the Second Level Cache. If the objects are stored in the L2 cache after the first query, then Hibernate will look there instead to satisfy the per-ID requests.
I highly recommend you pick up the book Java Persistence with Hibernate to learn more about this. Chapter 13 in particular covers optimizing queries, and how to use the cache effectively.