Hi,
i have two threads (each thread with its own session) which execute the some code. The code reads data from the
database and marks the datasets as "in work". It is vital for me that the changes one thread does are visible
to the other thread so that the some datasets are not processed by both threads.
This exactly is my problem. The changes of one thread (one session) seems not to be visible to the other. I already
tried to set FlushMode.ALWAYS but this didn't have any effect (at least not according to my problem).
Could anybody tell me what i did wrong or what do i have to configure to make this possible?
Thanks a lot!
Yours
Thomas
PS:
Actually the threads are concurrent requests to a web application currently using the session-per-request pattern.
PPS:
I created a test case to demonstrate the problem:
Table:
Code:
CREATE TABLE IF NOT EXISTS `hibernatetest` (
`pkhibernatetest` int(11) NOT NULL auto_increment,
`value` varchar(100) NOT NULL,
PRIMARY KEY (`pkhibernatetest`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Bean:
Code:
package beans;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "hibernatetest")
public class TestBean {
@Id
@Column(name = "pkhibernatetest", updatable = false, nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer pkhibernatetest;
@Column(name = "value", nullable = false, length = 100)
private String value;
public Integer getPkhibernatetest() {
return pkhibernatetest;
}
public void setPkhibernatetest(Integer pkhibernatetest) {
this.pkhibernatetest = pkhibernatetest;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Testcase:
Code:
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import beans.TestBean;
import utils.Hibernate;
public class Main implements Runnable {
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(new Main());
Thread t2 = new Thread(new Main());
t1.start();
t2.start();
}
public void run() {
Session sess = Hibernate.getSessionFactory().getCurrentSession();
sess.beginTransaction();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
/* just one thread at a time */
synchronized(Main.class) {
System.out.println(Thread.currentThread().getId() + ": check bean");
TestBean bean = (TestBean) sess.createCriteria(TestBean.class).add(Restrictions.eq("value", "blub")).uniqueResult();
if (bean == null) {
System.out.println(Thread.currentThread().getId() + ": do insert");
bean = new TestBean();
bean.setValue("blub");
sess.save(bean);
System.out.println(Thread.currentThread().getId() + ": insert done");
} else {
System.out.println(Thread.currentThread().getId() + ": bean already there");
}
}
sess.getTransaction().commit();
}
}
The code should only create one dataset... not 2. This is only a base code and does not contain any solution i already tried (different
FlushModes, commit of transaction and so on) to give you a clean code.