I have a simple class which starts 3 threads and saves a new object in each thread. But I am getting exception which i cannot understand. Can anyone help me understand why the exception?
package test;
import java.util.Date;
import org.hibernate.Session;
import domain.Event;
import util.HibernateUtil;
public class EventBeanTest {
public static void main(String [] args) {
Event e1 = new Event();
e1.setTitle("111");
e1.setDate(new Date());
Event e2 = new Event();
e2.setTitle("222");
e2.setDate(new Date());
Event e3 = new Event();
e3.setTitle("333");
e3.setDate(new Date());
Thread t1 = new Thread(new EventRunnable(e1));
Thread t2 = new Thread(new EventRunnable(e2));
Thread t3 = new Thread(new EventRunnable(e3));
t1.setName("event - 111");
t2.setName("event - 222");
t3.setName("event - 333");
t1.start();
t2.start();
t3.start();
}
}
class EventRunnable implements Runnable {
private Event event;
public EventRunnable(Event event) {
this.event = event;
}
public void run() {
System.out.println("Starting thread : " + Thread.currentThread().getName());
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.saveOrUpdate(event);
session.getTransaction().commit();
HibernateUtil.getSessionFactory().close();
System.out.println("Finishing thread : " + Thread.currentThread().getName());
}
}
And this is the relevant part of the log file showing the exception:
Hibernate: select max(EVENT_ID) from test.EVENTS
Hibernate: insert into test.EVENTS (EVENT_DATE, TITLE, EVENT_ID) values (?, ?, ?)
Hibernate: insert into test.EVENTS (EVENT_DATE, TITLE, EVENT_ID) values (?, ?, ?)
Hibernate: insert into test.EVENTS (EVENT_DATE, TITLE, EVENT_ID) values (?, ?, ?)
Apr 22, 2012 2:46:55 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH000030: Cleaning up connection pool [jdbc:mysql://localhost:3306/test]
Finishing thread : event - 333
Apr 22, 2012 2:46:55 PM org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction afterAfterCompletion
INFO: HHH000425: Could not close session; swallowing exception[org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor]] as transaction completed
Exception in thread "event - 222" org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:126)
at org.hibernate.internal.SessionFactoryImpl.getStatisticsImplementor(SessionFactoryImpl.java:1708)
at org.hibernate.internal.SessionFactoryImpl.getStatistics(SessionFactoryImpl.java:1704)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.afterTransaction(TransactionCoordinatorImpl.java:140)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.afterTransactionCompletion(JdbcTransaction.java:138)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:184)
at test.EventRunnable.run(EventBeanTest.java:60)
at java.lang.Thread.run(Thread.java:722)
Apr 22, 2012 2:46:55 PM org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction afterAfterCompletion
INFO: HHH000425: Could not close session; swallowing exception[org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor]] as transaction completed
Exception in thread "event - 111" org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:126)
at org.hibernate.internal.SessionFactoryImpl.getStatisticsImplementor(SessionFactoryImpl.java:1708)
at org.hibernate.internal.SessionFactoryImpl.getStatistics(SessionFactoryImpl.java:1704)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.afterTransaction(TransactionCoordinatorImpl.java:140)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.afterTransactionCompletion(JdbcTransaction.java:138)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:184)
at test.EventRunnable.run(EventBeanTest.java:60)
at java.lang.Thread.run(Thread.java:722)
EDIT 1
<?xml version='1.0' encoding='utf-8'?>
<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">vishnu</property>
<property name="connection.password">con02305</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="hibernate.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.internal.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">update</property> -->
<property name="default_schema">test</property>
<property name="show_sql">true</property>
<mapping resource="domain/Event.hbm.xml"/>
</session-factory>
Session object in Hibernate is not thread safe, you should not use the same session in different threads, unless you synchornize access to Session object.
Call .openSession()
instead of .getCurrentSession()
after getSessionFactory()
.
The sessionFactory
object is thread-safe but each Session
object should be single-threaded.
A Session is actually a Unit of Work which should be bound to the current executing Thread. A unit of work group multiple DML operations inside a single transaction which can succeed only if all operations succeed. So a session is atomic, and atomicity implies a single operating thread.
The Session is also the 1st Level Cache, so in the current Session you will always get the same Entity object reference, no matter how many times you call session.get() or session.load(). If a Session were thread-safe than during flush time you might execute other transaction intermediary changes. So a Session must be isolated from other executing Session, and isolation implies a single operating thread.
So, a Session is not meant to be thread-safe to preserve the atomicity and isolation requirements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With