Session is closed, on Hibernate 4.3 - java

I'm working over HIbernate 4.3 and I'm getting problems with sessions.. I'm trying to do some operations on database but didnt work properly. Im receiving the message that Session is closed.
My HibernateUtil class that create the session factory:
public class HibernateUtil
{
private static SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory()
{
try
{
if (sessionFactory == null)
{
Configuration configuration = new Configuration().configure(HibernateUtil.class.getResource("/hibernate.cfg.xml"));
StandardServiceRegistryBuilder serviceRegistryBuilder = new StandardServiceRegistryBuilder();
serviceRegistryBuilder.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = serviceRegistryBuilder.build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
return sessionFactory;
} catch (Throwable ex)
{
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory()
{
return sessionFactory;
}
public static void shutdown()
{
getSessionFactory().close();
}
}
My hibernate.cfg.xml:
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/db?autoReconnect=true</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- Use the C3P0 connection pool. -->
<property name="c3p0.min_size">3</property>
<property name="c3p0.max_size">10</property>
<property name="c3p0.timeout">1800</property>
<!-- Disable second-level cache. -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="cache.use_query_cache">false</property>
<property name="cache.use_minimal_puts">false</property>
<property name="max_fetch_depth">3</property>
<!-- Print SQL to stdout. -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- Drop and then re-create schema on SessionFactory build, for testing. -->
<property name="hbm2ddl.auto">create</property>
<!-- Bind the getCurrentSession() method to the thread. -->
<property name="current_session_context_class">thread</property>
<mapping class="model.User"/>
<mapping class="model.Point"/>
<mapping class="model.Layer"/>
<mapping class="model.AddressDatabase"/>
</session-factory>
</hibernate-configuration>
My HibernateListener that starts on the web.xml:
public class HibernateListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
HibernateUtil.getSessionFactory();
}
public void contextDestroyed(ServletContextEvent event) {
HibernateUtil.getSessionFactory().close();
}
}
My DAOFactory of Hibernate:
public class HibernateDAOFactory extends DAOFactory {
public UserDao getUserDao() {
return (UserDao)instantiateDAO(UserDaoImpl.class);
}
private GenericHibernateDao instantiateDAO(Class daoClass) {
try {
GenericHibernateDao dao = (GenericHibernateDao)daoClass.newInstance();
dao.setSession(getCurrentSession());
return dao;
} catch (Exception ex) {
throw new RuntimeException("Can not instantiate DAO: " + daoClass, ex);
}
}
// You could override this if you don't want HibernateUtil for lookup
protected Session getCurrentSession() {
return HibernateUtil.getSessionFactory().getCurrentSession();
}
}
And my HibernateDAO Factory, that instantiate the DAOs:
public class HibernateDAOFactory extends DAOFactory {
public UserDao getUserDao() {
return (UserDao)instantiateDAO(UserDaoImpl.class);
}
private GenericHibernateDao instantiateDAO(Class daoClass) {
try {
GenericHibernateDao dao = (GenericHibernateDao)daoClass.newInstance();
dao.setSession(getCurrentSession());t
return dao;
} catch (Exception ex) {
throw new RuntimeException("Can not instantiate DAO: " + daoClass, ex);
}
}
protected Session getCurrentSession() {
return HibernateUtil.getSessionFactory().getCurrentSession();
}
}
Relevant parts of GenericDAO:
public abstract class GenericHibernateDao<T, ID extends Serializable> implements GenericDao<T, ID> {
private Class<T> persistentClass;
private Session session;
#SuppressWarnings("unchecked")
public GenericHibernateDao() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
public void setSession(Session s) {
this.session = s;
}
protected Session getSession() {
if (session == null)
session = HibernateUtil.getSessionFactory().getCurrentSession();
return session;
}
public T create(T entity) {
getSession().save(entity);
return entity;
}
...
When I do sequences of operations on database I got the error.. The code below is a servlet and show how I instantiate my DAO and try to run some operations :
DAOFactory factory = DAOFactory.instance(DAOFactory.HIBERNATE);
userDao = factory.getUserDao();
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction;
User user = new User();
user.setEmail("xxx#gmail.com");
user.setName("xxx");
user = userDao.create(user);
tx.commit(); <-- WORKS FINE
session = HibernateUtil.getSessionFactory().getCurrentSession();
tx = session.beginTransaction;
User user2 = userDao.findByEmail("xxx#gmail.com"); <-- HERE HAPPENS THE ERROR.
I followed theses tutorials:
https://developer.jboss.org/wiki/SessionsAndTransactions
https://community.jboss.org/wiki/GenericDataAccessObjects
I tried to use OpenSesssion instead of getCurrentSession but I got this error on the first action on database:
org.hibernate.HibernateException: save is not valid without active transaction
And when I use the other one, I got the exception that the Sesssion is closed!
Any help will be appreciated.
Regards

Related

No CurrentSessionContext configured, while using getCurrentSession()

I am changing my code from openSession() to getCurrentSession() so it won't create connections at each request.
I have done code in class as:
public Session openSession(boolean current1){
int count = 0;
int MAX_COUNT = 10;
// this.printIdMap();
while( count++ < MAX_COUNT) {
try {
this.session = this.getSessionFactory().getCurrentSession();
this.transaction = this.session.beginTransaction();
this.IncDecCounter(true);
// this.session.getTransaction().commit();
break;
}
catch ( Exception e ) {
this.printIdMap();
e.printStackTrace();
try { this.session.close(); } catch( Exception e1 ) {}
}
}
return this.session;
}
I have checked in multiple places to set property in hibernate.cfg.xml file.
<property name="hibernate.current_session_context_class">thread</property>
I also tried
<property name="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocal‌​SessionContext</property>
but facing error as
org.hibernate.HibernateException: No CurrentSessionContext configured!
The hibernate version which I am using is 5.4.1
Lets imagine your Hibernate session manager class looks like this
public class HibernateSessionManager {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
ServiceRegistryBuilder serviceRegistryBuilder = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties());
return configuration.buildSessionFactory(serviceRegistryBuilder
.buildServiceRegistry());
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Use this property in your configuration file
<property name="hibernate.current_session_context_class">thread</property>
Instead of you currecnt one i.e
<property name="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocal‌​SessionContext</property>
And get your session with
Session session = HibernateSessionManager.getSessionFactory().openSession();

Change location of hibernate.properties file while using hibernate.cfg.xml

We provide db credential in hibernate.cfg.xml as
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">url</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.connection.password">password</property>
<session-factory>
<hibernate-configuration>
Either we can provide these properties here or in hibernate.properties in classpath. But I want them to come from an external file. I couldn't find a way in hibernate to change the path of default hibernate.properties file.
Please help.
[EDIT]
The method in java which generates sessionFactory object
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
// Create the session factory from hibernate.cfg.xml
Configuration configuration = new Configuration();
StandardServiceRegistryBuilder serviceRegistryBuilder =
new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
return configuration.buildSessionFactory(serviceRegistryBuilder.build());
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Programmatically, you can load XML and properties like this:
public class MyHibernate {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
URL r1 = MyHibernate.class.getResource("/hibernate.cfg.xml");
Configuration c = new Configuration().configure(r1);
try {
InputStream is = MyHibernate.class.getResourceAsStream("/hibernate.properties");
Properties props = new Properties();
props.load(is);
c.addProperties(props);
} catch (Exception e) {
LOG.error("Error reading properties", e);
}
return c.buildSessionFactory();
} catch (Throwable ex) {
LOG.error("Error creating SessionFactory", ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Through Spring
You can use a PropertiesFactoryBean to read-in the properties from your file and configure your LocalSessionFactoryBean:
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="hibernateProperties">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">path-to-properties-file</property>
</bean>
</property>
...
</bean>
Hope it be useful.

Receiving org.hibernate.ResourceClosedException "This TransactionCoordinator has been closed"

I have a servlet, running on Tomcat 6, that uses Hibernate 4.1.6 and c3p0 0.9.1.2, and I am getting too much org.hibernate.ResourceClosedException, with the message "This TransactionCoordinator has been closed".
I've already checked that beginTransaction() and rollback() or commit() are done before the thread is reused by another call.
At hibernate.cfg.xml, I have
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.connection.url">jdbc:mysql://host/database</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="show_sql">true</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">50</property>
<!-- mappings start here -->
...
</session-factory>
</hibernate-configuration>
and I am using a HibernateUtil.java to create a static sessionFactory for my application and I use it to control my transactions:
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
Configuration configuration = new Configuration();
configuration.configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void shutdown() {
getSessionFactory().close();
}
public static void beginTransaction() {
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
}
public static void commit() {
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
}
public static void rollback() {
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();
}
}
When I start using the database in a servlet, my code is basically this:
try {
HibernateUtil.beginTransaction();
// do stuffs
HibernateUtil.commit();
} catch (RuntimeException e) {
HibernateUtil.rollback();
throw e;
} catch (Exception e) {
HibernateUtil.rollback();
throw e;
}
Where am I doing wrong?
I have closed a session after completing transaction and in the new session i have used the object of previous session, this caused me an 'Transaction Coordinator has been closed'
I have edited the code to use new session object, now the error is resolved

Hibernate : closing the session factory does not close the c3p0 connection pool

I recently started using hibernate along with c3p0 as the ORM in my application. However, when I close the session factory, the connection pool does not close itself! This is the one and only place in my application where I do anything with a session.
StatelessSession session = null;
Transaction transaction = null;
try {
session = sessionFactory.openStatelessSession();
transaction = session.beginTransaction();
List<Thingy> list = session.getNamedQuery("getAvailableThingy").list();
transaction.commit();
return list;
} catch (Exception error) {
if (transaction != null) {
transaction.rollback();
}
throw error;
} finally {
if (session != null) {
session.close();
}
}
This is my hibernate.cfg.xml configuration file
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="javax.persistence.validation.mode">none</property>
<property name="hibernate.connection.release_mode">after_transaction</property>
<property name="hibernate.c3p0.minPoolSize">1</property>
<property name="hibernate.c3p0.maxPoolSize">2</property>
<property name="hibernate.c3p0.acquireIncrement">1</property>
<property name="hibernate.c3p0.initialPoolSize">1</property>
<property name="hibernate.c3p0.timeout">30</property>
<property name="hibernate.c3p0.maxIdleTimeExcessConnections">5</property>
<property name="hibernate.c3p0.idleConnectionTestPeriod">300</property>
</session-factory>
</hibernate-configuration>
Note that the reason for the very short idle connection it that its the only way I found yet to make my integration tests to pass. They open and close the session factory a lot and thus I always run out of connections. As we are at the beginning of the project, I guess it's not a very sustainable strategy in the long run.
An "interesting" thing to note is that despite the fact that I set the initial connection pool to one, c3p0 still try to open two connection on start. My guess is that there is some kind of hidden session somewhere that don't get closed (but where? beat me).
So how can I get that annoying connection pool to close itself up?
Additional info :
how I create and destroy my session factory
import static com.google.common.base.Preconditions.*;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Provides;
#Singleton
public class PostgisConnection implements Provider<SessionFactory>, AutoCloseable {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final ConnectionInfo connectionInfo;
private SessionFactory sessionFactory = null;
#Inject
public PostgisConnection(ConnectionInfo connectionInfo) {
this.connectionInfo = connectionInfo;
}
public AutoCloseable open() {
checkState(sessionFactory == null, "Connections to postgis are already open");
logger.info("Creating sessionFactory for connection to postgis: {}", connectionInfo.getJdbcUrl());
sessionFactory = newPostgisSessionFactory(connectionInfo);
return this;
}
#Override
public void close() throws Exception {
try {
if (sessionFactory != null) {
logger.info("Closing sessionFactory for postgis: {}", connectionInfo.getJdbcUrl());
sessionFactory.close();
checkState(sessionFactory.isClosed(), "Session factory should be closed at this point");
}
} catch (Exception error) {
logger.error("Error closing SessionFactory", error);
}
}
#Provides
public SessionFactory get() {
return sessionFactory;
}
public static SessionFactory newPostgisSessionFactory(ConnectionInfo connectionInfo) {
Configuration configuration = configurationWith(connectionInfo);
return configuration.buildSessionFactory(registryFrom(configuration));
}
private static Configuration configurationWith(ConnectionInfo connectionInfo) {
Configuration configuration = new Configuration();
setConnectionInfo(connectionInfo, configuration);
configuration.addURL(PostgisConnection.class.getResource("mapping.hbm.xml"));
configuration.configure(PostgisConnection.class.getResource("hibernate.cfg.xml"));
return configuration;
}
private static void setConnectionInfo(ConnectionInfo connectionInfo, Configuration configuration) {
configuration.setProperty("hibernate.connection.url", connectionInfo.getJdbcUrl());
configuration.setProperty("hibernate.connection.username", connectionInfo.getUsername());
configuration.setProperty("hibernate.connection.password", connectionInfo.getPassword());
}
private static ServiceRegistry registryFrom(Configuration configuration) {
return new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
}
}
Hibernate version : 4.1.10.Final
C3p0 version : 0.9.1.2
I had the same issue and successfully used the work-around offered in this bug report:
private void closeSessionFactory(SessionFactory factory) {
if(factory instanceof SessionFactoryImpl) {
SessionFactoryImpl sf = (SessionFactoryImpl)factory;
ConnectionProvider conn = sf.getConnectionProvider();
if(conn instanceof C3P0ConnectionProvider) {
((C3P0ConnectionProvider)conn).close();
}
}
factory.close();
}
You have to reference the hibernate-c3p0-4.x.x jar.
I had the same issue and successfully used the ehnanced (January 2014) work-around offered in this bug report:
private static boolean closeSessionFactoryIfC3P0ConnectionProvider(SessionFactory factory) {
boolean done = false;
if(factory instanceof SessionFactoryImpl) {
SessionFactoryImpl sf = (SessionFactoryImpl)factory;
ConnectionProvider conn = sf.getConnectionProvider();
if(conn instanceof C3P0ConnectionProvider) {
((C3P0ConnectionProvider)conn).close();
try {
Thread.sleep(2000); //Let give it time...it is enough...probably
} catch (InterruptedException e) {
e.printStackTrace();
}
done = true;
}
factory.close();
}
return done;
}
You have to reference the hibernate-c3p0-4.x.x jar.

hibernate main method call

I'm very new to Hibernate and just wanted to query the initial basics.
I've created my Hibernate bean as such...
package com.behaviour.chapter1;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class User {
private int userId;
private String firstName;
#Id
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
I've configured my hibernate.cfg.xml and db connection there. My question is simply, how do I actually call this from a main method and use it in Hibernate3.6.6? I was following a tutorial online but it was for Hibernate3.2 and it seems to be a bit different. If anyone could show me just a really simple main method calling this bean, creating a new user (that would create a user in this table) it would be greatly appreciated. Also - if anyone has any good Hibernate tutorial links that would be great :)
Thanks,
There are several ways of doing this, it is a matter of design choice, a basic way to achieve this will be to create the session factory from hibernate.cfg.xml file. Make sure the file can be located at your classpath.
And using the class below, create a Session Factory object which is then used to open up new Session's
public class HibernateUtil
{
private static final SessionFactory sessionFactory;
static
{
try
{
// Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
}
catch (Throwable ex)
{
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory()
{
return sessionFactory;
}
}
Now to create a new user, do:
public class DaoFactory
{
public void create(Object obj)throws Exception
{
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(obj);
session.getTransaction().commit();
}
}
Main
public static void main(String[] args)
{
try
{
User user = new User();
user.setFirstName("david99world");
DaoFactory factory = new DaoFactory();
factory.create(user);
}
catch(Exception ex)
{
ex.printStackTrace(System.out);
}
}
EDIT
Your hibernate.cfg.xml should look something like this:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">none</property>
<mapping class="com.behaviour.chapter1.User"/>
</session-factory>
</hibernate-configuration>
I'm assuming you've set up your persistence.xml already. If so, you can use the following Java code. You'll have to substitute the "..." with your JDBC setup data and persistence unit.
private static final String PERSISTENCE_UNIT = "...";
final Map<String, String> properties = new HashMap<String, String>();
properties.put("javax.persistence.jdbc.driver", "...");
properties.put("javax.persistence.jdbc.url", "...");
properties.put("javax.persistence.jdbc.user", "...");
properties.put("javax.persistence.jdbc.password", "...");
final EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT, properties);
final EntityManager em = emf.createEntityManager();
User user = new User();
user.setUserID(0);
user.setFirstName("David");
em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit();
HTH
Raku
Hibernate tutorials
Hibernate tutorial-1
Hibernate tutorial -2
Do you need a Session object to access the persistence unit. These objects are provided by SessionFactory objects.
Check the Hibernate reference guide.

Categories

Resources