Hibernate/JPA query blocks forever - java

My application is experiencing a strange issue where sometimes it blocks forever when attempting to run an SQL query against the database, even if that is a small select statement on one single row.
This may occur at different points in the application, whenever it tries do execute a query (SELECT, UPDATE, etc.), which indicates this is perhaps a configuration issue.
With a tcpdump I was able to tell the query is never actually sent to the Oracle database, despite hibernate show_sql saying otherwise.
The worst thing is that as soon as the application blocks on a query for the first time, any other database queries in that machine (on different Threads) block in the same way, even though the machine is not nearly at its load capacity and can do any non-database work.
The only solution to this has been restarting the application, which runs as expected (with SQL queries) until at some random point in time (even days after) it blocks forever again...
This runs on
Hibernate 5.2.9.Final
Apache camel 2.19.2
applicationContext.xml
<!-- JPA Setup -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myPersistenceUnit" />
<property name="persistenceUnitPostProcessors">
<list>
<bean class="test.package.ReportingDbConnSetup" />
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
</bean>
</property>
</bean>
<bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager">
<bean class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</property>
</bean>
persistence.xml
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="jboss.as.jpa.managed" value="false" />
<property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver" />
<property name="org.hibernate.flushMode" value="ALWAYS" />
<!-- username, password and connection url hidden -->
<property name="hibernate.hbm2ddl.auto" value="" />
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JDBCTransactionFactory" />
<property name="hibernate.current_session_context_class" value="thread" />
<property name="connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
<property name="hibernate.c3p0.acquire_increment" value="1" />
<property name="hibernate.c3p0.idle_test_period" value="60" />
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.max_size" value="12" />
<property name="hibernate.c3p0.max_statements" value="35" />
<property name="hibernate.c3p0.timeout" value="120" />
<property name="hibernate.c3p0.acquireRetryAttempts" value="3" />
<property name="hibernate.c3p0.acquireRetryDelay" value="210" />
</properties>
Here is an example code block that might hang forever with no additional information:
#PersistenceUnit(unitName = "myPersistenceUnit")
private EntityManagerFactory entityManagerFactory;
public void saveOrUpdate(Object o){
EntityManager em = null;
try{
em = entityManagerFactory.createEntityManager();
Session session = em.unwrap(Session.class);
txn = session.beginTransaction();
session.saveOrUpdate(o);
txn.commit();
}
catch(Exception e){
if (txn !=null && txn.isActive()) {
txn.rollback();
}
LOG.error(e);
}
finally{
if(em != null && em.isOpen()){
try{
em.close();
} catch (Exception e){
LOG.error(e);
}
}
}
}

Related

Tomcat database connection pool slow in high throughput

I have soap webservice written in Spring 2.X and which connect to Teradata and return the result to client. To connect the data based I am using Tomcat JDBC Connection Pool as the DataSource.
In peak hour (9AM to 6PM) application get about 60k transactions requests. I observed some of the transactions goes in hung state and return response in 2-3 minutes . I suspect some transaction goes in wait status and once connection is available in pool then complete the transactions.
Below is the configuration for the DataSource.
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
destroy-method="close">
<property name="driverClassName" value="com.teradata.jdbc.TeraDriver"/>
<property name="url" >
<util:constant static-field=" _DB_HOST"/>
</property>
<property name="username">
<util:constant static-field=" DB_USER"/>
</property>
<property name="password">
<util:constant static-field=" DB_PWD"/>
</property>
<property name="initialSize" value="1" />
<property name="maxActive" value="50" />
<property name="minIdle" value="0" />
<property name="maxWait" value="-1" />
<property name="minEvictableIdleTimeMillis" value="1000" />
<property name="timeBetweenEvictionRunsMillis" value="1000" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
<qualifier value="txnMngr"/>
</bean>
// using JdbcTemplate to read the data from data base.
Here are my questions:
Is there any issue with above configuration based on the load which I mentioned for my application?
Is there any way I can monitor the DB connection pool uses?

Spring | JPA | Hibernate - Returns only 1000 entities

I'm new in Java Web Development and for last several days I've been having a big problem, I can not make JPA/Hibernate to return more than 1000 entities.
In my database I have around 1600 Assortment entities but whatever I try, I can't get more than 1000 of them, even when I try to count them so I would be able to paginate requests, COUNT(...) returns 1000.
I know that problem is not on database server because I've already made PHP server side scripts that work flawlessly with this SQL server.
I've tried using Query, NativeQuery and Criteria. But nothing returns more than 1000 entities.
I'm sure I googled everything, and really do not have any idea what else to do, please help.
My code is below and thank you in advance!
spring-context.xml
...
<!-- SQL Server Datasource with Commons DBCP connection pooling -->
<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://XXX;database=XXX;user=XXX;password=XXX;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;" />
<property name="validationQuery" value="select 1" />
<property name="validationQueryTimeout" value="1000" />
<property name="testOnBorrow" value="true" />
</bean>
<!-- EntityManagerFactory -->
<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit" />
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Transaction Manager -->
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
...
persistence.xml
<persistence xmlns="..." xmlns:xsi="..." version="2.0" xsi:schemaLocation="...">
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2008Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<property name="hibernate.generate_statistics" value="true"/>
<property name="hibernate.show_sql" value="false"/>
</properties>
</persistence-unit>
</persistence>
AssortmentService.java
#Transactional
public List<Assortment> getWholeAssortment() {
String searchQuery = "SELECT a FROM Assortment a";
List<Assortment> result = entityManager.createQuery(searchQuery, Assortment.class).getResultList();
return result;
}
#Transactional
public int getAssortmentCount(){
String searchQuery = "SELECT COUNT(1) FROM test_assortment";
int result = (Integer) entityManager.createNativeQuery(searchQuery).getSingleResult();
return result;
}
#Transactional
public List<Assortment> getAssortmentWithCriteria(){
CriteriaQuery<Assortment> criteria = entityManager.getCriteriaBuilder().createQuery(Assortment.class);
criteria.select(criteria.from(Assortment.class));
List<Assortment> result = entityManager.createQuery(criteria).getResultList();
return result;
}

how to use multiple datasources with spring-data-jpa? [duplicate]

This question already has answers here:
Spring Boot, Spring Data JPA with multiple DataSources
(6 answers)
Closed 4 years ago.
I read all the related questions and tried all of them but still can't make my configuration straight.
I've two databases and i want to use them as datasources in my application.
Here is my context file:
<jee:jndi-lookup id="firstDataSource" jndi-name="java:/comp/env/jdbc/firstDS" expected-type="javax.sql.DataSource" />
<jee:jndi-lookup id="secondDataSource" jndi-name="java:/comp/env/jdbc/secondDS" expected-type="javax.sql.DataSource" />
<bean name="persistenceProvider" class="org.hibernate.jpa.HibernatePersistenceProvider"></bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="thisEntityManagerFactory">
<property name="dataSource" ref="firstDataSource"/>
<property name="packagesToScan" value="com.a.b.first.model"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="showSql" value="true"/>
<property name="databasePlatform" value= "org.hibernate.dialect.Oracle10gDialect"/>
<property name="database" value="ORACLE"/>
</bean>
</property>
<property name="persistenceUnitName" value="firstPersistenceUnit" />
<property name="persistenceProvider" ref="persistenceProvider"></property>
<property name="jpaProperties">
<value>
hibernate.generate_statistics = true
hibernate.cache.use_second_level_cache = true
hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
hibernate.cache.use_query_cache = true
<!--hibernate.hbm2ddl.auto=create-->
</value>
</property>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="otherEntityManagerFactory">
<property name="dataSource" ref="secondDataSource"/>
<property name="packagesToScan" value="com.a.b.second.model"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="showSql" value="true"/>
<property name="databasePlatform" value= "org.hibernate.dialect.Oracle10gDialect"/>
<property name="database" value="ORACLE"/>
</bean>
</property>
<property name="persistenceUnitName" value="secondPersistenceUnit" />
<property name="persistenceProvider" ref="persistenceProvider"></property>
<property name="jpaProperties">
<value>
hibernate.generate_statistics = true
hibernate.cache.use_second_level_cache = true
hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
hibernate.cache.use_query_cache = true
<!--hibernate.hbm2ddl.auto=create-->
</value>
</property>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="thisTransactionManager">
<property name="entityManagerFactory" ref="thisEntityManagerFactory"/>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="otherTransactionManager">
<property name="entityManagerFactory" ref="otherEntityManagerFactory"/>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<tx:annotation-driven transaction-manager="thisTransactionManager" />
<tx:annotation-driven transaction-manager="otherTransactionManager" />
<jpa:repositories base-package="com.a.b.first.intf" entity-manager-factory-ref="thisEntityManagerFactory" transaction-manager-ref="transactionManager"/>
<jpa:repositories base-package="com.a.b.second.intf" entity-manager-factory-ref="otherEntityManagerFactory" transaction-manager-ref="otherTransactionManager" />
Problem is when i try to use a repository interface which is located under package com.a.b.second.intf, it goes to firstDataSource and throws a SQLSyntaxErrorException with message "ORA-00942: table or view does not exist". Because there is no such table in the first database.
There is a line in tho logs for each EntityManagerFactory, saying
Building JPA container EntityManagerFactory for persistence unit
'default'
And in the next line it prints PersistenceUnitInfo for this EntityManagerFactory. The "Non JTA datasource" property of the PersistenceUnitInfo is same for both EntityManagerFactories. I guess that means both persistence units uses the same datasource.
What am i missing?
Thanks.
In your service layer you should have something like this:
#Service
#Transactional("thisTransactionManager")
public class ThisService{
#Autowired
private com.a.b.first.intf.Repo1 repo1;
}
#Service
#Transactional("otherEntityManagerFactory")
public class OtherService{
#Autowired
private com.a.b.second.intf.Repo1 repo1;
}
This way, when you call a service method, the TransactionInterceptor can load the appropriate transaction manager, associated to the EntityManagerFactory you want to operate with.

Hibernate Too Many Connections With Cache

I'm using hibernate to try and retrieve a cached query.
#Transactional
public interface ProductDAO extends JpaRepository<Product, Long> {
#QueryHints({ #QueryHint(name = "org.hibernate.cacheable", value = "true") })
Product findByCode(String code);
}
I'm load testing and I'm doing this in a large loop of 1000 iterations.
for (int i = 0; i < 500; i++) {
URL myURL = new URL("http://localhost:8080/test");
URLConnection myURLConnection = myURL.openConnection();
myURLConnection.connect();
myURLConnection.getContent();
}
I've checked with showsql and I can see only 1 SQL statement is generated for my first hit to the DB after which it is cached.
Yet I still get the following error even though no SQL is being shown:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Too many connections
My Hibernate properties:
#hibernate properties
hibernate.dialect = ${hibernate.dialect}
hibernate.show_sql = false
hibernate.hbm2ddl.auto = ${hibernate.hbm2ddl}
hibernate.c3p0.min_size = 10
hibernate.c3p0.max_size = 100
hibernate.c3p0.timeout = 300
hibernate.c3p0.max_statements = 50
hibernate.c3p0.acquire_increment = 5
hibernate.c3p0.idle_test_period = 3000
hibernate.cache.use_second_level_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
hibernate.cache.use_query_cache=true
Database config:
<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${db.url}" />
<property name="driverClassName" value="${db.driverClassName}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="${hibernate.dialect}" />
</bean>
</property>
<property name="jpaProperties" ref="hibernateProperties" />
<property name="packagesToScan">
<array>
<value>com.exammple.model</value>
</array>
</property>
</bean>
<bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:/spring/hibernate.properties" />
</bean>
<bean id="sessionFactory" factory-bean="entityManagerFactory" factory-method="getSessionFactory" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<jpa:repositories base-package="com.example.dal" entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager" repository-impl-postfix="CustomImpl" />
The problem is your configuration you aren't using a connection pool.
You are configuring a DriverManagerDataSource which isn't a proper connection pool. You are injecting this bean into the LocalContainerEntityManagerFactoryBean which renders your hibernate.connection and hibernate.c3p0 properties useless, they aren't used.
Solution is quite easy drop the hibernate.c3p0 and hibernate.connection properties and replace the DriverManagerDataSource with a proper pool implementation. I would recommend HikariCP over C3P0 but that is personal preference.
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="springHikariCP" />
<property name="connectionTestQuery" value="SELECT 1" />
<property name="dataSourceClassName" value="${db.driverClassName}" />
<property name="dataSourceProperties">
<props>
<prop key="url">${db.url}</prop>
<prop key="user">${db.username}</prop>
<prop key="password">${jdb.password}</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg ref="hikariConfig" />
</bean>
This problem may be have multiple issues:
You don't close your database connections.
You set a maximum connection pool pool size that exceeds the maximum connections allowed of your database server. When the number of clients exceeds the number of maximum allowed connections, you'd get an exception like this.
I could use FlexyPool to monitor the connection pool usage and find out if connections are leaking or if they are leased for long times.
Update
As M. Deinum already said, you are not using Connection Pooling.
You can still use the Hibernate C3P0 properties, but you have to remove the dataSource from the LocalContainerEntityManagerFactoryBean:
<property name="dataSource" ref="dataSource" />
This way Hibernate can use the hibernate.c3p0 properties.

Spring/JPA/Hibernate persist entity : Nothing happen

I'm trying to make an application with Spring 3, JPA 2 and Hibernate 3.
I have a problem when y persist an entity : nothing happen ! Data are not inserted in database, and not query is executed.
But when i'm using a request like query.getResultList() a select works correctly.
So I think my problem is only on a persist/update and on the transaction manager but i'm not really good with spring.
Can you help me please ?
Here are my configuration files :
My applicationContext.xml
<jee:jndi-lookup id="soireeentreamis_DS" jndi-name="jdbc/soireeentreamis" />
<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="defaultDataSource" ref="soireeentreamis_DS" />
<property name="dataSources">
<map>
<entry key="soireeentreamisDS" value-ref="soireeentreamis_DS" />
</map>
</property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="soireeentreamisPU" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
</bean>
</property>
</bean>
<bean id="soireeentreamisTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<tx:annotation-driven transaction-manager="soireeentreamisTransactionManager" />
<context:annotation-config />
</beans>
My persistence.xml
<persistence-unit name="soireeentreamisPU"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>soireeentreamisDS</non-jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
My service
#Service
#Transactional("soireeentreamisTransactionManager")
public class UserServiceImpl implements UserService ...
My dao
#Repository
public class UserDaoImpl extends GenericDaoImpl<User, String> implements
UserDao {
#PersistenceContext(unitName = "soireeentreamisPU")
private EntityManager em;
public void persist(final User entity) {
em.persist(entity);
}
}
Can somebody help me please?
I find similar problem a while ago. In my case I needed to add line below to my dispacher-servlet.xml. So I need this in 2 places (applicationContex.xml and dispacher-servlet.xml)
<tx:annotation-driven />
And to clear something out, you didn't show your service methode that "store" object, but I believe that it's annotated with #Transactional - cause wihout this one you want create new transaction.
This happened to me recently. The problem is as you say a transactional problem, add the #Transactional annotation to all the methods that update the DB. Then add the CGLIB library to your calsspath or add it to your pom.xml if you are using Maven, this is necessary for spring make transactions. Even if I did it on a different way I hope it can help you. Here is my db.xml where I have all the data base related spring configuration.
<!-- Scans within the base package of the application for #Components to configure as beans -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="${db.dialect}" />
</bean>
</property>
</bean>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"
destroy-method="close">
<property name="driverClass" value="${db.driver}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<property name="idleConnectionTestPeriodInMinutes" value="1" />
<property name="idleMaxAgeInMinutes" value="4" />
<property name="maxConnectionsPerPartition" value="30" />
<property name="minConnectionsPerPartition" value="10" />
<property name="partitionCount" value="3" />
<property name="acquireIncrement" value="5" />
<property name="statementsCacheSize" value="100" />
<property name="releaseHelperThreads" value="3" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="jpaDialect" ref="jpaDialect"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
And here is my persistence.xml
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="pu-app" transaction-type="RESOURCE_LOCAL">
</persistence-unit>
You need to add the model object into the persistence.xml file. Right below the provider element add
<class>com.your.domain.object.User</class>

Categories

Resources