簡體   English   中英

休眠,多線程和CascadeType.ALL

[英]Hibernate, Multithreading and CascadeType.ALL

在多線程環境中,

這有效

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。最終版,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;
    }
}

EntityManagerFactory是創建成本高昂的線程安全對象,旨在由所有應用程序線程共享。 它通常在應用程序啟動時創建一次。

EntityManager是一種廉價的, 非線程安全的對象,應針對單個業務流程,單個工作單元使用一次,然后丟棄。 ...

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

我不確定自己在做什么,但是如果您正在多個線程中使用相同的靜態EntityManager,那就是您的問題。

EntityManagerFactory是您要共享的線程安全對象,但是您應該為正在執行的每個請求/工作單元創建一個新的EntityManager。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM