MyBatis - connection to MySQL randomly dropping - java

*UPDATE: I found a method which didn't close the session after openning. I think this might be the cause. Will test and report later. *
We are using MyBatis with our GWT Java web application. The problem is that sometimes an exception happens while trying to read or write to the database with MyBatis. What could be the cause? Any subsequent queries will work. It seems like the connection is timed out and needs to be refreshed. This happens sometimes through the day, we don't see any pattern in this. We tried different configurations to no avail.
org.apache.ibatis.exceptions.PersistenceException:
### Error opening session. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Communications link failure during rollback(). Transaction resolution unknown.
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Communications link failure during rollback(). Transaction resolution unknown.
The MyBatis configuration file:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/project"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
<property name="poolMaximumActiveConnections" value="20"/>
<property name="poolMaximumIdleConnections" value="5"/>
<property name="poolPingEnabled" value="true"/>
<property name="poolPingQuery" value="select 1"/>
</dataSource>
</environment>
</environments>
Update 1
The exception is thrown in different "DAOs", it's not specific to a single method/call.
A general method might look like this:
#Override
public Entity get(String id) throws Exception {
LogHelper.logMethodStart(logger, "get", "id", id);
SqlSession session = null;
try {
session = GenericDao.SESSION_FACTORY.openSession();
EntityDao mapper = session.getMapper(EntityDao.class);
return mapper.get(id);
} catch (Exception e) {
logger.error(e);
throw e;
} finally {
if (session != null) {
session.close();
}
}
}
Where the session factory class consists of:
public static SqlSessionFactory SESSION_FACTORY;
static {
logger.info("SqlSessionFactory init started.");
String aResource = "iBatisConfig.xml";
Reader reader;
try {
reader = Resources.getResourceAsReader(aResource);
} catch (IOException e) {
throw new RuntimeException(e);
}
SESSION_FACTORY = new SqlSessionFactoryBuilder().build(reader);
try {
reader.close();
} catch (IOException e) {
logger.error(e);
}
SESSION_FACTORY.getConfiguration().addMappers("com.example.project.server.dao");
logger.info("SqlSessionFactory init end.");
}

Problem solved for me. I went though all the methods that were opening a session and one session was not being closed - coding error. Thus the connection pool ran out of free connection sometimes.

Related

Message redelivery in Spring with JBOSS

I am using Spring SimpleMessageListenerConatiner where acknowledgement mode is 2 (client acknowledge) and Queue is Solace.
When I am throwing runtime exception from my unit test, means standalone spring config, messages are redelivering without any issue, but same code is not working when I am deploying my application in JBOSS.
public class MyListener implements MessageListener {
public void onMessage(Message message) {
try {
throw new ConnectionException("Error in Connection");
} catch (ConnectionException e) {
LOGGER.error("Throwing exception...");
throw new MyRuntimeException("Throwing exception");
} finally {
LOGGER.info("Done...");
}
}
Spring config is:
<bean id="solaceMessageListener" class="org.springframework.jms.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="solaceConnectionFactory"/>
<property name="destinationName" value="QueueName"/>
<property name="messageListener" ref="myListener"/>
<property name="concurrency" value="1"/>
<property name="destinationResolver" ref="destinationResolver" />
<property name="sessionAcknowledgeMode" value="2"/>
</bean>
Constaint:
1. I cannot use DefaultMessageListenerContainer
2. Session Transacted true is working but we have not to use it.

Why can't Hibernate see newly created data?

Im creating a simple web app using Spring and Hibernate that has something to do with online shopping. My program is doing well when inserting new data using hibernate. When I check the db, the data is there. The problem is, the moment I fetch the new data I created, it gets nothing. I tried to put data in the db manually and hibernate gets the data. I'm sorry if this seems a beginner question, I'm studying Hibernate as a part of my training as a jr web developer. First, I wanna show you the config:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/------" />
<property name="username" value="----" />
<property name="password" value="------" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<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>
</props>
</property>
<property name="packagesToScan" value="com.qbryx.domain" />
</bean>
Here is the code for adding a new product:
#Override
public void addProduct(Product product) {
Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Query query = session.createSQLQuery(DAOQuery.HQL_ADD_PRODUCT).setParameter("upc", product.getUpc())
.setParameter("category", product.getCategory().getCategoryId())
.setParameter("name", product.getName()).setParameter("description", product.getDescription())
.setParameter("price", product.getPrice());
query.executeUpdate();
transaction.commit();
} catch (HibernateException e) {
if (transaction != null)
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
#Override
public void addProductStock(InventoryProduct inventoryProduct) {
Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Query query = session.createSQLQuery(DAOQuery.HQL_ADD_PRODUCT_STOCK)
.setParameter("upc", inventoryProduct.getUpc())
.setParameter("stock", inventoryProduct.getStock());
query.executeUpdate();
transaction.commit();
} catch (HibernateException e) {
e.printStackTrace();
} finally {
session.close();
}
}
This code does fine with adding a new product together with the stock. Here is my code for fetching the product:
#Override
public InventoryProduct getInventoryProductByUpc(String upc) {
InventoryProduct product = null;
Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Query query = session.createQuery(DAOQuery.HQL_GET_INVENTORY_PRODUCT)
.setParameter("upc", upc);
product = (InventoryProduct) query.getSingleResult();
transaction.commit();
} catch (HibernateException e) {
if (transaction != null)
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
return product;
}
I don't understand why Hibernate can fetch data that is manually added to the database but not the data added through Hibernate. I need help. Thanks!

Spring JDBC connection issue-Connections could not be acquired from the underlying database

I am stuck into a big trouble that i cannot connect the oracle 11g database form my Spring MVC application.
The error i am getting is
HTTP Status 500 - Request processing failed; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Connections could not be acquired from the underlying database!
also,
in the stack trace i'm getting the error-
java.lang.ClassNotFoundException: oracle.jdbc.OracleDriver
If you can help me to resolve the issue, it will be a great help.
I am providing my configuration and coding details below:
Default-servlet.xml
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxPoolSize" value="${jdbc.maxPoolSize}" />
<property name="minPoolSize" value="${jdbc.minPoolSize}" />
<property name="maxStatements" value="${jdbc.maxStatements}" />
<property name="testConnectionOnCheckout" value="${jdbc.testConnection}" />
</bean>
<bean id="userAuthenticationRepository"
class="com.era.repository.impl.UserAuthenticationRepositoryImpl">
<property name="dataSource" ref="dataSource" />
</bean>
UserAuthenticationRepositoryImpl.java
#Repository
public class UserAuthenticationRepositoryImpl implements UserAuthenticationRepository {
#Qualifier("dbDataSource")
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public User getUserAuthentication(User userToBeAuthenticated) {
// TODO Auto-generated method stub
String query = "select id, name, role from User where login =";
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
StringBuilder queryString = new StringBuilder();
queryString.append(" SELECT ")
.append( "*" )
.append(" FROM table_name ")
.append(" WHERE login = ? ");
Object[] parameterList = { userToBeAuthenticated.getLogin() };
SqlRowSet dataRow = jdbcTemplate.queryForRowSet(queryString.toString(), parameterList);
if (dataRow.next()) {
System.out.println("Query executed successfully");
}
return null;
}
As you are using maven, note here you can't directly get Oracle driver jar to .m2 due to licence restriction, so you may need to manually download and place it to your repository.You may find this link helpful.

hibernate delete second level jpa2.0

I need in my application to remove all data from a cachable table.
I suposed that to delete all contents, I had to remove the second level cache, then use a truncate.
#Entity
#Table(name = "\"cpf_formacode\"")
#Cacheable
public class CpfRefFormaCode implements Serializable {
.......
}
the Dao method:
public void deleteAll() {
SessionFactory sf = em.unwrap(SessionFactory.class);
sf.getCache().evictEntityRegion(CpfRefFormaCode.class);
em.createNativeQuery("TRUNCATE TABLE cpf_formacode").executeUpdate();
}
persistence file:
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="org.hibernate.FlushMode" value="commit" />
<!-- property name="hibernate.hbm2ddl.auto" value="create-drop" / -->
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.cache.infinispan.cachemanager" value="java:jboss/infinispan/hibernate" />
<property name="hibernate.cache.region.factory_class" value="org.jboss.as.jpa.hibernate4.infinispan.InfinispanRegionFactory" />
<property name="hibernate.cache.infinispan.statistics" value="true" />
</properties>
the error i have :
17:50:17,161 ERROR [org.jboss.as.ejb3.tx.CMTTxInterceptor] (http--127.0.0.1-8080-2) javax.ejb.EJBTransactionRolledbackException: Hibernate cannot unwrap interface org.hibernate.SessionFactory
17:50:17,163 ERROR [org.jboss.ejb3.invocation] (http--127.0.0.1-8080-2) JBAS014134: EJB Invocation failed on component CpfRefFormaCodeDao for method public void com.agefos.corp.business.dao.CpfRefFormaCodeDao.deleteAll(): javax.ejb.EJBTransactionRolledbackException: Hibernate cannot unwrap interface org.hibernate.SessionFactory
Caused by: javax.persistence.PersistenceException: Hibernate cannot unwrap interface org.hibernate.SessionFactory
I finished by findig the solution,
The problem that i was trying to clean the cach before deleting the data, and it was not the best practice
public void deleteAll() {
try {
TypedQuery<MyEntity> query = em.createQuery("From MyEntity f", MyEntity.class);
query.setHint("org.hibernate.cacheable", true);
List<MyEntity> result = null;
result = query.getResultList();
if (!result.isEmpty()) {
for (MyEntity f : result) {
em.remove(f);
}
}
em.flush();
} catch (Exception e) {
throw new PersistanceException("An error occurred while attempting to delete an instance of an object : " + entityClass, e);
}
}
the problem was resolved by adding the
em.flush();
In other words, flush tells Hibernate to execute the SQL statements needed to synchronize the JDBC connection's state with the state of objects held in the session-level cache. so i was abel to save other entities without ID problems

JDBC Datasource returning NULL

I have this working java code that serve as the "datasource":
public final class PMF {
static Driver driver = null;
static String url = "jdbc:jiql://local";
static Properties props = new Properties();
static {
String password = "jiql";
String user = "admin";
props.put("user",user);
props.put("password",password);
try {
Class clazz = Class.forName("org.jiql.jdbc.Driver");
driver = (Driver) clazz.newInstance();
} catch (Exception e){
e.printStackTrace();
}
}
public static Connection get() {
try{
return driver.connect(url,props);
} catch (java.sql.SQLException e){
e.printStackTrace();
}
return null;
}
}
When I tried to adapt this code for Spring with the code below:
jdbc.properties
jdbc.driverClassName=org.jiql.jdbc.Driver
# development
jdbc.url=jdbc:jiql://local
jdbc.username=admin
jdbc.password=jiql
applicationContext.xml
<!-- placeholders -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="/WEB-INF/jdbc.properties"/>
</bean>
<!-- data source -->
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
The "datasource" gets null when I do this in the DAO:
#Autowired
private DataSource dataSource;
What could be causing the datasource to be null?
It looks like it was a DAO issue and not JDBC issue. I re-created the app using Spring STS and everything went working.

Categories