【问题标题】:Hibernate, Multithreading and CascadeType.ALLHibernate、多线程和 CascadeType.ALL
【发布时间】:2013-08-01 00:26:58
【问题描述】:

在多线程环境中,

这行得通

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;
    }
}

【问题讨论】:

  • 您的第一个代码块中是否有错字?没有t2。

标签: java multithreading hibernate


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 所以这个在 save() 前面的“同步”真的没有帮助吗?我在多个线程中使用单个 EntityManager,但我将它封装在一个对象中,以确保对它的每次访问都是原子的。
  • entityManagers 应该为每个业务案例创建,这就是我的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多