Hibernate late lazy loading in Java - java

If I load a City object from DB using Hibernate session, and then using the same session which has not been used for an hour, if I do a city.getCountry() which should lazy load the Country object, I get an Exception (Connection marked as broken because of SQLSTATE(08003)). I got two general questions:
Is lazy loading just another new JDBC connection and totally
independent connection under the hood?
What kind of parameters in hibernate connection pool configuration I
need to tune to increase the timeout for these kind of situations?
I'm not using transactions.
I'm using HikariCP and my DB is Postgrsql.

Related

Spring Transaction (#Transaction) with Plain JDBC without JdbcTemplate

I have plain JDBC code which is doing transaction management using Connection Interface. I wanted to switch to Spring Transaction Management in small steps.
Firstly I want to provide PlatformTransactionManager for my datasource and annotate my class / methods with #Transaction and keep my other logic same ie. using connection / PreparedStatement etc.
All the examples, which I see use JdbcTemplate. I was wondering can Spring Transaction be used without JdbcTemplate?
Technically it is possible to use #Transactional without JdbcTemplate . But if you try to do it , you will sooner or later find that you are re-inventing what the things that are already done by JdbcTemplate.
What #Transactional does is that before executing a #Transactional method , it will help you to get a JDBC Connection from the DataSource , and start a transaction on this Connection .The JDBC Connection will then stored in a ThreadLocal.
That means if you do it without JdbcTemplate , you have to manually get this Connection from that ThreadLocal such that you can create a JDBC Statement from it for executing your SQL. Not to mention you have to manually release the JDBC resources such Statement , ResultSet etc. properly by yourself which all of these things are already take care by JdbcTemplate.
But if you have already implemented these JDBC codes manually and just want to let #Transactional to handle the transaction , you could try to inject the DataSource to your bean and then use the following method to get the Connection for your JDBC codes use :
Connection connection = DataSourceUtils.getConnection(dataSource);
Also checkout JdbcTemplate#execute(ConnectionCallback<T> action) , it is useful for migrating the existing JDBC codes that expects a JDBC Connection to work on to JdbcTemplate.
Yes it's possible. Adding a #Transactional annotation to your methods, as long as they follow the correct procedure should make your methods transactional. But as others have mentioned if you're in the process of updating your app you might as well ditch plain JDBC and move across to Spring JPA/JDBC (depending on which version of Spring you're using).

Hibernate vs Spring connection acquisition strategy

I'm trying to understand when exactly a database connection is aquired in an application that uses hibernate as an ORM & Spring for transaction management.
In this article, it says:
If the transaction manager decides to create a new transaction, then it will:
create a new entity manager
bind the entity manager to the current thread
grab a connection from the DB connection pool
bind the connection to the current thread
However here it says :
Hibernate defers the database connection acquisition until the current transaction has to execute its first SQL statement (either triggered by a read or a write operation). This optimization allows Hibernate to reduce the physical transaction interval, therefore increasing the chance of getting a connection from the pool.
I can't understand how can Hibernate delay the connection aquisition if Spring decides to aquire it before.
I can't understand how can Hibernate delay the connection aquisition
if Spring decides to aquire it before.
The decision is taken by the transaction manager and so potentially by the JpaTransactionManager/HibernateTransactionManager
Hibernate 5.2.0 introduces new property hibernate.connection.provider_disables_autocommit
With this Hibernate can delay the database connection acquisition until there is a JDBC Statement to execute. otherwise the database connection is acquired when entering the #Transactional service method.
So to allow Spring wires this property into the JPATransactionManager during the setup of spring context you have to set this property in your application.properties/yaml -->
spring.jpa.properties.hibernate.connection.provider_disables_autocommit=true
Last thing required to do this --> setAutoCommit to false on the connection pool provider (by default HikariCP since Spring boot 2)
spring.datasource.hikari.auto-commit=false

Can we use multiple db instances in hibernate at a time?

My requirement is, I have two db instances in db2 with same db schema. We take backup of db every year. So we have db like dbinstance_2014, dbinstance_2015 and dbinstance_2016.
My application is working on 2016 instance. I need to create report year wise in that case I need to use older instances. I have create two methods to create session factory. One method will create current years dbinstance connection and other will dynamically create connection to older db.
Current year sessionFactory is used throughout the application. In case of report generation I am trying to use another method which creates sessionfactory dynamically.
But I am getting exception:
org.hibernate.HibernateException: No CurrentSessionContext configured
How can I resolve this error?

How to disable connection pooling in Hibernate

I have a web application that currently uses c3p0 and Hibernate to connect to a Firebird 1.5 database.
I am facing a problem from time to time where the database just stops responding, even trying to manually restart the service doesn't have any effect, and it doesn't generate any logs, so I have to manually reboot the machine to get it working again.
I think that maybe Firebird hangs when the pool tries to acquire a specific number of connections or something like that. So, I need to test my app without connection pooling, to check if this is or is not the problem.
I can't simply remove c3p0 configs from persistence because this way Hibernate would use its own integrated connection pool. So how to do it?
The most flexible solution is to use an explicit DataSource, instead of configuring the connection pooling through Hibernate. One option to configure a non-pooling DataSource is by using DriverManagerDataSource:
#Override
protected Properties getProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
//log settings
properties.put("hibernate.hbm2ddl.auto", "update");
//data source settings
properties.put("hibernate.connection.datasource", newDataSource());
return properties;
}
protected ProxyDataSource newDataSource() {
DriverManagerDataSource actualDataSource = new DriverManagerDataSource();
actualDataSource.setUrl("jdbc:hsqldb:mem:test");
actualDataSource.setUsername("sa");
actualDataSource.setPassword("");
ProxyDataSource proxyDataSource = new ProxyDataSource();
proxyDataSource.setDataSource(actualDataSource);
proxyDataSource.setListener(new SLF4JQueryLoggingListener());
return proxyDataSource;
}
This way you can choose a pooling or a non-pooling DataSource.
To get a better understanding of you connection pooling resources usage, you can configure FlexyPool to collect metrics for:
concurrent connections
concurrent connection requests
data source connection acquiring time
connection lease time
maximum pool size
total connection acquiring time
overflow pool size
retries attempts
I found documentation for hibernate 3.3 and 4.3 that says:
Just replace the hibernate.connection.pool_size property with
connection pool specific settings. This will turn off Hibernate's
internal pool.
Hibernate will use its org.hibernate.connection.C3P0ConnectionProvider
for connection pooling if you set hibernate.c3p0.* properties
So remove hibernate.connection.pool_size and any hibernate.c3p0... properties from configuration, than connection pooling is disabled.
Adding to Vlad's answer:
If somebody still faces this:
Be sure to remove "hibernate-c3p0" from your classpath, if exists, since this will automatically enable MChange c3p0 connection pool.
Another option that, you can close the connection manually when closing the entity manager:
....
SessionImpl ses = (SessionImpl) session;
close(ses.connection());
try {
session.close();
} catch (Exception e) {
logger.error(e);
}
........
Note: the above manual closing will work with the default pool of hibernate, not hibernate default one.
Good Luck

EJB3 DataSource DataSource.getConnection

In a CMT J2EE environement (Container Managed Transaction) what transaction / connection is used when I JDNI-lookup for a DataSource object and invoke DataSource.getConnection?
Is this connection part of the (potentially distributed) transaction? Does getConnection() return the same Connection every time I call it for the same DataSource object? I only know using Connections by the same EntityManager using native SQL statements.
It is something that keeps me puzzling. As I understood the SessionContext defines a transactional system that is used throught every time I use a datasource. I have the problem that inside a session bean a DataSource.getConnection() is used and this connection is then closed. If a problem is encountered SessionContext.setForRollBack(true) is issued.
Therefore how does the transactional context of a service relate to a DataSource?
If we spawn a new Connection each time a datasource is used or at least looked up, I have problems to understand things I already know. Any clarification would be wonderful. I know container managed transaction and other systems, but the actual behavior of DataSource is totally beyond me.
In Java EE a transaction is a concept that is not exclusive to databases, for example JMS connection sessions can also be part of container managed transaction. The idea is if one or more than one method is running under container managed transaction boundary, the container will commit or rollback the transaction as needed.
In data base related data source, there are multiple layers, fist is the managed pool of connection which is maintained by the container, second is the actual connection management of the database driver with the database, in Java a Connection is an abstraction for a session with a database and not a physical connection, that is managed by the driver.
With the above context, your questions could be addressed viz.:
what transaction / connection is used when I JDNI-lookup for a DataSource object and invoke DataSource.getConnection.
Under container managed transaction, though it is implementation dependent, a connection/session with the database is associated that is marked with the transaction boundary. The actual physical connection could be shared with the database by the driver but that is transparent to application as well as the container.
Is this connection part of the (potentially distributed) transaction? Does getConnection return the same Connection every time I call it for the same DataSource object?
Refer above, a Connection has no relation with the underlying socket to the database as opened by the driver. It is logically a separate session and if within transaction boundary, the same session is associated with the connection retrieved from the data source, how this is implemented is part of the container design
I have the problem that inside a session bean a DataSource.getConnection is used and this connection is then closed
In a pooled implementation for connection a Connection.close() has no impact, the connection is returned to the pool(http://commons.apache.org/proper/commons-dbcp/api-1.3/org/apache/commons/dbcp/PoolableConnection.html), this behaviour is similar for all pools. So clsing a connection does not necessarily disassociate it from container transaction boundary, though a connection should not be closed within container managed transaction. Similarly, commit, setAutoCommit, rollback must not be called from within CMT as this will issue the following command equivalent to the actual database and the behaviour of the transaction after that will undefined.
Have a look at the declaration of the #Resource annotation.
It includes a shareable attribute that allows you to specify connection sharing behaviour. It defaults to true, which means that you will get connection sharing automatically if you do nothing.
This attribute is also included in the XML schema for any resource-ref defined datasources that you may lookup using JNDI.
All resources (JDBC, JMS, ResourceManager) that are included during an invocation are enrolled in the current transaction. You may sometimes need to specify the use of XA for this to work correctly.

Categories