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