Hibernate connections remain open - java

We're facing huge versions upgrade of the codebase, in that codebase we're using hibernate and jdbi to connect to a postgres 12 db.
JDBI version is not changed in this upgrade, Hibernate version was 5.1.5.Final and has been updated to 5.3.10.Final.
Now I've a lot of trouble with connection that remain open, I report some tests that I've done (the problem are on reading).
In the previous version I do three query through hibernate (and for each one i use close method on entity manager after I get the result) and them all remain in idle in transaction, then I perform a jdbi query and all hibernate sessions will disappear.
With the new version, same test, I've to increase connection pool size through
<property name="hibernate.connection.pool_size" value="3"/></properties>
but connections remain always idle in transaction and never been closed.
I've noticed that adding commit method before closing the entity manager will leave a number of connection open equals to the number that I've placed as pool size.
Can someone explains how connection works in hibernate? Especially why in the previous version connections were closed automatically after doing a jdbi query.

Related

how to get the size of hibernate connection pool?

I have an app that is written in java spring.
It uses hibernate to handle connections to postgres DB.
I want to get the size of the connection pool, but it isn't defined on the app's hibernate configurations.
So I guess it uses hibernate default size, which is 1?
That sounds very low to me.
How can I be sure what is the size of connection pool?
I read that it is recommended to use third party manager for this, but I don't think it's in used also.

How to check if you're still connected to the database with jpa

I'm trying to check the database connection with jpa using the EntitityManager/Session class.
To check both cases (connected/not connected), I simply start/deactivate the service mysql before running the code.
Asking simple sql queries to the database is out of mind since it doesn't cover all cases.
I already tried:
Session session = entityManager.unwrap(Session.class)
session.isConnected();
But that always returns true...
When I disable the mySQL service I want session.isConnected() to return false, but it always returns true;
Is there any other way to check for the database connection(using any other classes maybe)?
Short answer: don't
Long answer: if you're developing an application where this is important, you will probably be using some sort of database connection pooling framework, like the
Tomcat JDBC pool
Apache Commons DBCP
HikariCP
C3P0 Connection pool
This will manage many important aspects for you, including connection lifecycle. In tomcat jdbc for example you can specify:
testOnBorrow="true"
validationQuery="select 1 from sysibm.dual"
This on an IBM DB2 database will test whether a connection went stale every time you use it, and also swap it out for a fresh one if the select fails. Done this way, you will never have to worry about this on the level of you application code.

Force spring to use only one connection for transaction

I have a spring (version 3.2.15) application that uses more than one connection in a transactional method.
My use case is:
Call to transactional method (which opens one connection)
Query for an entity (which opens and closes another connection)
Persist the entity
End of the method (closes the first connection)
The problem is that I have a limited number of connections, and I need to ensure that only one connection is used per transactional method. This problem causes a dead lock in my application because there are much more transactions opened than the number of connections available.
Is there any way that I can use the same connection spring uses to maintain the transaction on my method? I have already tried the hibernate option hibernate.connection.release_mode in after_statement mode, but an error occurs when hibernate is trying to commit the transaction. 
I've read the spring transaction documentation but I cannot figure out how to configure spring to behave this way.

Does hibernate use PreparedStatement by default

"Hibernate always uses PreparedStatement for calls to the database" Quoted here.
If so then where does hibernate cache compiled queries, does DB driver cache them.
I read about c3p0. If hibernate caches PreparedStatement by default then what is the use of hibernate.c3p0.max_statements in c3p0.
If hibernate does not do it by default then is connection pooling mandatory for caching prepared statements.
Could somebody please clarify these.
Caching prepared statements only makes sense in the scope of a specific JDBC connection. So, you will only gain something out of caching prepared statements when a sort of connection pooling is available to the ORM layer. Otherwise, you get a new "physical" JDBC connection every time you create a Hibernate Session (which is not very efficient normally). Without any connection pooling caching prepared statements is only useful in the scope of a single JDBC connection / Hibernate Session. This happens because without any connection pooling the "physical" connection is actually closed and won't be reused - instead always a new connection will be created using the database driver, whenever it is required.
One other thing that you need to take into account, is that the number of open prepared statements on a single JDBC connection is limited (the limitation is vendor dependent and varies between driver implementations as far as I know). So, in a pooled connections scenario, the pooling implementation will likely need to know how many open prepared statements may be maintained on each of the pool's "physical" underlying JDBC connections. Likely, a "least used prepared statements gets closed first" policy is implemented, but this is pure speculation on my part.
I hope this makes some sense. Whenever I mention a "physical" JDBC connection I mean an actually new TCP/IP connection to the database. Connections obtained by a connection pool will typically decorate/wrap a "physical" one.
Edits to answer your questions more directly:
Hibernate most likely uses and caches PreparedStatements (this is very basic JDBC optimization). The question is does this caching happen on the statements created by a "physical" or a pool provided JDBC connection. Without a pool caching the PreparedStatements only optimizes the part of the application execution that uses a specific PreparedStatement twice in the scope of a specific Hibernate Session. With a pool the same PreparedStatement will (effectively) be used across many Hibernate Session instances that will happen to use the same underlying "physical" connection.
The property hibernate.c3p0.max_statements of your hibernate configuration will most likely configure the C3PO pool instance (which I am pretty sure is created automatically for you) and this configuration has something to do with the fact about the number of open prepared statements being limited in a "physical" JDBC connection.

Oracle connection/query timeout

Is it possible to specify connection/query timeout for the Oracle database queries? Either on Oracle side or in Oracle's JDBC driver (10.2.0.4)? So, that Java client just got an error back after, let's say, 2 minutes instead of waiting until Oracle finishes executing the query?
If you are executing the query in the context of a transaction, the transaction timeout value of the JTA transaction monitor will be the determinant to query timeout. The configuration for this depends from one application server to another.
At an individual query level (in the absence of a JTA transaction monitor), the setQueryTimeout method can be used to set the timeout on the execution of a Statement/PreparedStatement/CallableStatement object.
Update
setQueryTimeout is not to be relied on, although it works (atleast from a J2SE client). It works via the JDBC driver performing a full round-trip to the Oracle database server. Then, it is upto the database to halt execution of the query. Don't rely on it for time critical applications.
Have a look at Oracle profiles. This allows you to specify several limits at the database level. One of them is a maximum CPU time per query.
If you have queries running for more than 2 minutes on a regular basis you might want to do some tuning of your queries first.
According to http://www.javamonamour.org/2012/09/oraclenetconnecttimeout.html
oracle.net.READ_TIMEOUT for jdbc versions < 10.1.0.5 oracle.jdbc.ReadTimeout for jdbc versions >=10.1.0.5
So if you are using a JDBC driver version 10.1.0.5 or higher, then oracle.jdbc.ReadTimeout is the correct property.
Setting oracle.jdbc.ReadTimeout helped to timeout the jdbc calls. I have used it in a production spring boot app by specifying datasource properties as below
spring.datasource.hikari.connection-timeout=1000
spring.datasource.hikari.dataSourceProperties=oracle.jdbc.ReadTimeout=2000
Note: Earlier this app was using tomcat connection pool and after setting the above properties for the same, timeouts were happening but the pool was not able to handle the closed connection objects efficiently. Therefore, I switched to hikariCP and got lot better results. I have made a video simulating the slow jdbc calls which compares the results with tomcat and hikari connection pools while using the ReadTimeout property.

Categories