在多线程环境中,
此作品
Box box = new Box("B");
Toy t1 = box.addNewToy("t1");
Toy t2 = box.addNewToy("t2");
synchronized (em) {
em.getTransaction().begin();
em.persist(t1);
em.getTransaction().commit();
}
synchronized (em) {
em.getTransaction().begin();
em.persist(t2);
em.getTransaction().commit();
}
但这不是
Box box = new Box("B");
Toy t1 = box.addNewToy("t1");
synchronized (em) {
em.getTransaction().begin();
em.persist(t1);
em.getTransaction().commit();
}
Toy t2 = box.addNewToy("t2");
synchronized (em) {
em.getTransaction().begin();
em.persist(t2);
em.getTransaction().commit();
}
我得到的错误如下:"对象引用未保存的瞬态实例","具有相同标识符值的不同对象已经与会话关联"
有什么想法吗?
这是一个重现问题的最小Maven项目:http://www.2shared.com/file/bGLmJ6aO/example.html
详情
java版" 1.7.0_17",hibernate 4.2.3.Final,Ubuntu 11.04 natty,SQLite
class Toy {
@ManyToMany(mappedBy="toys",fetch = FetchType.LAZY, cascade = CascadeType.ALL)
public List<Box> getBoxes() { return boxes; }
public void setBoxes(List<Box> boxes) { this.boxes = boxes; }
}
class Box {
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
public List<Toy> getToys() { return toys; }
public void setToys(List<Toy> toys) { this.toys = toys; }
public Toy addNewToy(String name) {
Toy toy = new Toy();
toy.setName(name);
toy.boxes.add(this);
toys.add(toy);
return toy;
}
}
答案 0 :(得分:1)
EntityManagerFactory是一个昂贵的创建线程安全对象,旨在由所有应用程序线程共享。它创建一次,通常是在应用程序启动时。
EntityManager是一个廉价的,非线程安全的对象 对于单个业务流程,单个工作单元,可以使用一次, 然后丢弃。 ...
请参阅:http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html_single/#transactions-basics
我不确定你在做什么但是如果你从多个线程使用相同的静态EntityManager那么这就是你的问题。
EntityManagerFactory
是您要共享的线程安全对象,但您应该为正在执行的每个请求/工作单元创建一个新的EntityManager。