I have been using Hibernate for some time, and everything has been working fine. Today, I ran into a concurrency bug, and I decided to write a test case to simulate multiple threads reading/writing. So, here is my test scenario.
Thread A -> opens session1 and attempts to read a user object, should not find it
Thread B -> opens session2, creates the user object, closes session
Thread A -> closes session1
Thread A -> opens session3, and attempts to read the user object, should find it, close session3
The problem is that even after the object has been written to the database, Thread A is unable to find it. If I move the close of session1 before the object gets written, everything works fine. But, this doesn't make too much sense, since the object is being written in a totally separate thread. What really worries me is that the scenario I am listing above is pretty common in web applications making use of a request thread pool.
What am I doing wrong? Any help would be greatly appreciated. The following is the code I am using to test:
Code:
Session session1 = factory.openSession();
// Perform the read using session1 on thread1
try
{
list = session1.find( "from UserData" );
}
catch( Exception ex ) { ex.printStackTrace(); }
System.out.println(
"#### thread: " + Thread.currentThread().getName() +
", list size: " + list.size() );
// Create the user using session2 on thread2
Thread createThread =
new Thread()
{
public void run()
{
try
{
Session session2 = factory.openSession();
Transaction txn = session2.beginTransaction();
UserData user = new UserData();
user.setName( "foo" );
session2.save( user );
txn.commit();
session2.close();
System.out.println(
"#### thread: " + Thread.currentThread().getName() +
", wrote user object" );
}
catch( Exception ex ) { ex.printStackTrace(); }
}
};
createThread.start();
createThread.join();
/* If I move this above the creation of the user object (in the separate thread)
everything works fine. Why? */
session1.close();
Session session3 = factory.openSession();
// Perform the read using session3 on thread1
try
{
list = session3.find( "from UserData" );
}
catch( Exception ex ) { ex.printStackTrace(); }
System.out.println(
"#### thread: " + Thread.currentThread().getName() +
", list size: " + list.size() );
session3.close();
Here is the output I am receiving:
Code:
[junit] DEBUG | HibernateManager:buildSessionFactory | built session factory for:/test.cfg.xml
[junit] Hibernate: select userdata0_.id as id, userdata0_.name as name, userdata0_.password as password, userdata0_.emailAddress as emailAdd4_ from user userdata0_
[junit] #### thread: main, list size: 0
[junit] Hibernate: insert into user (name, password, emailAddress) values (?, ?, ?)
[junit] #### thread: Thread-0, wrote user object
[junit] Hibernate: select userdata0_.id as id, userdata0_.name as name, userdata0_.password as password, userdata0_.emailAddress as emailAdd4_ from user userdata0_
[junit] #### thread: main, list size: 0