How to handle max database connections with Hibernate? - java

Below is Hibernate configuration from Hibernate.xml
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
.....
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Below is code from GenricDaoImpl class (code 1)
#Override
public T save(T t) {
Session session = getSessionFactory().openSession();
Transaction tx=session.beginTransaction();
session.saveOrUpdate(t);
tx.commit();
session.close();
return t;
}
and other code from project (code 2)
Query executeQuery = getSession().createQuery(hql);
UserProfileuser = (UserProfile) executeQuery.uniqueResult();
Above both codes I am using in project. My question is which coding need to follow ? code 1 or code 2 to avoid max connections error.? I can connect max 1000 connections with database. But in some cases it is going more than 1000 . So i want to maintain database connection minimum.
Please guide me.

Using 1000 database connections doesn't sound like a very good idea. Each extra database connection requires extra RAM and increases the likelihood of concurrency issues (deadlocks).
Since you use C3P0 you should have a max connection size:
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
If you run out of connections then it may be because:
you don't close the Hibernate Session, and the associated JDBC connection doesn't get released to the pool
your queries take too long to execute and so they don't release connections fast enough
I recommend using a connection pool size utility, such as FlexyPool to understand better the database connection usage patterns.
Regarding the two choices:
The 1st example contradicts the automatic session management support offered by Spring. When you use Spring you should not manage Hibernate Sessions yourself. You should let the transaction manager call the appropriate Hibernate initializing callbacks on a new transaction boundary.
In your example, if the session throws an exception, the session will not be closed and the connection might be dangling around. That's because you haven't used a try/finally block for releasing the Session.
The 2nd example is better, but you need to wrap it into a #Transactional service.

Related

MySQL : EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost

I have an Spring application with quartz scheduler for batch processing. It was working fine from last 4 years. There is a batch which runs on every 1 minute. But from last few days suddenly when the batch is trying to fetch some data we are getting org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Could not open connection
This batch runs throughout the day but some times gives this exception and all other batches fails to connect to MySQL. So we are restarting the application and it is working fine.
Data source config
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url">
<value>${DATABASE_URL}</value>
</property>
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="username">
<value>${DATABASE_USER}</value>
</property>
<property name="password">
<value>${DATABASE_PASSWORD}</value>
</property>
</bean>
Session factory connection pooling configuration
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
<!-- Configurations specific to c3p0 connection pooling -->
<prop key="hibernate.c3p0.acquire_increment">5</prop>
<prop key="hibernate.c3p0.idle_test_period">1800</prop>
<prop key="hibernate.c3p0.max_size">600</prop>
<prop key="hibernate.c3p0.max_statements">50</prop>
<prop key="hibernate.c3p0.min_size">5</prop>
<prop key="hibernate.c3p0.timeout">1800</prop>
</props>
</property>
<property name="annotatedClasses">
<list> .... </list>
</property>
</bean>
May be it is the problem with the mysql running your db-server.
change the mysql configuration in your db-server
add the bind-address in mysql.cnf under [mysqld] section
bind-address=your_spring_application_ip
also change the accessing host for the mysql user.
run the following query in mysql
update mysql.user set host='%' where user='your_username';
flush privileges;
then restart the mysql service
sudo systemctl restart mysql
Recently we had kind of the same issue. Our application failed to connect to aws Aurora instance. What we ended up doing changing sql driver to mariadb one. Hope this will help.

spring application takes too long to start

I have a java application in which I'm using Spring and Hibernate frameworks. On my production environment, it would take too long (upto an hour) to start the application properly, as in, within 10 minutes. I could see the login page but if I try to login, it would just keep processing. Only after an hour or so, I would be able to login.
After some research I found that by default hibernate.temp.use_jdbc_metadata_defaults is set to true, in which case it takes time, so I set it to false. Now my application is starting up quickly in my local system when I point it to production db to test. Even in test environment it performs as expected. But when I rolled it out to production, it worked fine initially but now it again is taking too long to start up.
Any idea how to approach it now?
EDITED: adding more details:
initial startup time is huge. once it is up then pages would load fine. we are using postgres db and have multiple schemas. Please suggest what other details are needed
Below is session factory onfiguration:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mydb"/>
<property name="entityInterceptor" ref="nullToEmptyStringInterceptor" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.multiTenancy">SCHEMA</prop>
<prop key="hibernate.tenant_identifier_resolver">path_to.DataBaseResolver</prop>
<prop key="hibernate.multi_tenant_connection_provider">path_to.MultiTenantProvider</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>path_to_model_package</value>
</list>
</property>
</bean>
Below is entityManagerFactory configuration
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="mydb" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
<property name="persistenceUnitName" value="myPersistenceUnit" />
<property name="packagesToScan" >
<list>
<value>path_to_model_package</value>
</list>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
<prop key="hibernate.jdbc.use_get_generated_keys" >true</prop>
</props>
</property>
</bean>
I don't think we can tell you what the problem is. It will be something to do what the applications is doing during startup, and we can only guess what that would be.
However ...
What you should do is to profile the application during startup, and use the profiling to identify where most of the time is being spent. Then look to see if you can work out what it its doing ... and optimize it.
It would also be work turning on GC logging to see if memory usage / garbage collection is part of the problem. Ditto for checking if database activity is a significant bottleneck.
Finally, an important step in finding the cause of this problem is likely to be understanding the internal architecture of the application. Especially if this is code that has been passed from developer to developer over a number of years.
As you did not posted full details of your problem, like hibernate, spring and other app configurations so suggesting you a solution is bit difficult. The following could be possibilities:
Somewhere there could be deadlock during application load time. For example, so batch job running in background before the container completely starts.
If your db schema is always checked to be updated after the container start and your db is having a large number of tables and columns with a lot of data inside then it would definitely take time before that application loading completes.
Check server configurations like if there is another instance of application running in parallel which is causing delay.

Spring app should start even though DB is down

I have a spring app which do minimal operations with DB.
And I have a requirment that my application should run under the absence of DB(or when db is down).Below is my datasource configuration.
<bean id="dt31DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" depends-on="systemPropertyInitializer"
p:driverClass="${dt31.driver_class}"
p:jdbcUrl="${dt31.url}"
p:user="${dt31.username}"
p:password="${dt31.password}"
p:idleConnectionTestPeriod="1000"
p:maxPoolSize="4"
p:minPoolSize="2"
p:maxIdleTime="2000"
p:unreturnedConnectionTimeout="600"
p:contextClassLoaderSource="library"
p:privilegeSpawnedThreads="true"
p:initialize=false
/>
<bean id="dt31SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dt31DataSource"/>
<property name="packagesToScan" value="com.t22.dt31"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
${dt31.dialect}
</prop>
<prop key="hibernate.show_sql">
false
</prop>
<prop key="hibernate.hbm2ddl.auto">
update
</prop>
</props>
</property>
</bean>
I found a page in google,saying to use "initialize: false" in spring data source configuration.But I am using "ComboPooledDataSource" datasource which does not have this property.Is there any other way to achieve this ?
The application service layer can operate with two DAO layers (file system and database), so when the DB is down you catch the connection acquire exception and switch to the file system instead.
Having two sources of truth is going to make it difficult to preserve consistency across two different data sources, especially if one resource is not available.
When both resources are available you can use XADisk and Bitronix for XADataSource and JTA transaction management.

Hibernate 4 default transaction timeout value

I'm getting this error:
2014-11-14 17:39:44 [WARN]SqlExceptionHelper:143 SQL Error: 0, SQLState: 08S01
2014-11-14 17:39:44 [ERROR]SqlExceptionHelper:144 Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
2014-11-14 17:39:44 [ERROR]BackupService:245 org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Could not open connection
Seems that Hibernate has a small transaction timeout for my job, but I can not find what is the default timeout value. I did not find it also in hibernate documentation, I find how to change it, but not the default value.
This is my hibernate configuration:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.test.db.entity</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">false</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.search.autoregister_listeners">false</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop>
</props>
</property>
</bean>
Do you know what is the default timeout value for an hibernate transaction with this configuration?
I got the same exception. I googled and found your question without answer :)
I changed "Timeout Seconds:" from 300 to 1000 (possible to increase more, it depends on your transaction timeout) on "mydomain->Configuration->JTA" on Weblogic Console or increase JTA timeout on your application server.
Then, for hibernate.cfg.xml you may check this answer: Hibernate/MySQL Connection Timeout
It works.

Connection pool problem with Spring and programmatic transaction management

I need your help in order to solve connection pool problem with Spring.
I’m using Spring with Java 1.4 (no annotation).
Here is the datasource and the connection pool definition:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>${database.jdbcName}</value>
</property>
<property name="url" value="jdbc:sybase:${database.url}">
</property>
<property name="username">
<value>${database.username}</value>
</property>
<property name="password">
<value>${database.password}</value>
</property>
<property name="maxActive">
<value>${database.maxActive}</value>
</property>
<property name="maxIdle" >
<value>${database.maxIdle}</value>
</property>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SybaseDialect</prop>
<prop key="show_sql">true</prop>
<prop key="hibernate.connection.release_mode">after_transaction</prop>
<prop key="hibernate.dbcp.maxWait">100000</prop>
<prop key="hibernate.connection.autocommit">false</prop>
<prop key="cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
</props>
</property>
...
When all the connections are active, if the system need a new connection I got a message saying “opening JDBC connection” and all the process are stopped. I don’t understand why all the threads are locked.
All services and DAO classes are defined as singletons in Spring application context.
Any idea?
Thanks for your help.
Béranger
What values are you using for maxActive and maxIdle? I can give you a more definitive answer if I know those values, but in the meantime you can also try changing the value of hibernate.dbcp.maxWait from 100000 to 1 and test your application again.
Also make sure you haven't you accidentally made some of your DAO methods synchronized.
This was a weird one but I finally solved my problem.
The reason of this connection locking was that I used both declarative and programmatic transaction management with Spring. I think that my programmatic transaction management was wrong.
Here is the code used to begin a transaction:
//Return Spring context
ApplicationContext context = ApplicationContextHolder.getContext();
// transactionManager
PlatformTransactionManager transactionManager = (PlatformTransactionManager) context.getBean("txManager");
//Set propagation required
DefaultTransactionDefinition td = new DefaultTransactionDefinition();
td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// Begin
TransactionStatus transactionStatus = transactionManager.getTransaction(td);
As you can see I set the programmatic transactions as “required”. But when those transactions were started in a transactional context, Spring didn’t recognized the current transaction and started a new one. It leaded to a connection locking...
I solved this mystery by removing the programmatic transaction management.

Categories