1

在多线程环境中,

这有效

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”,休眠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;
    }
}
4

1 回答 1

1

EntityManagerFactory 是一个创建成本高、线程安全的对象,旨在由所有应用程序线程共享。它创建一次,通常在应用程序启动时创建。

EntityManager 是一个廉价的、非线程安全的对象,应该使用一次,用于单个业务流程、单个工作单元,然后丢弃。...

请参阅:http ://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html_single/#transactions-basics

我不确定您在做什么,但是如果您从多个线程中使用相同的静态 EntityManager,那么这就是您的问题。

EntityManagerFactory是您要共享的线程安全对象,但您应该为正在执行的每个请求/工作单元创建一个新的 EntityManager。

于 2013-08-01T01:03:28.260 回答