Hibernate在集合上循环时丢弃会话

时间:2018-03-15 04:19:01

标签: java hibernate jpa

我在LazyInitializationException: failed to lazily initialize a collection of roles, could not initialize proxy - no Session的集合上循环时遇到此异常MyTable。 e.g:

@Entity
@Table(name = "MY_TABLE")
public class MyTable {
    @Id
    private String id;

    @OneToMany
    @JoinColumn(
        name = "key", referencedColumnName = "key_from_other_table",
        updatable = false, insertable = false
    )
    private List<OtherTable> objects;
    public List<OtherTable> getObjects() {
        return objects;
    }
    public void setObjects(List<OtherTable> objects) {
        this.objects = objects;
    }
}

然后在普通的for循环中

for (MyTable myTable : collectionOfMyTables) {
    myTable.getObjects();
}

异常将在循环到达第3 myTable时发生,其中它在列#34; key_from_other_table&#34;中具有相同的值。与myTable集合中的任何先前collectionOfMyTables相符。

如果所有myTable个对象在列&#34; key_from_other_table&#34;中有不同的值,则不会发生异常。

e.g:

MY_TABLE
id | key_from_other_table | some_values
---------------------------------------
 1 | SET_A                | xxx
 2 | SET_B                | yyy
 3 | SET_C                | zzz

OTHER_TABLE
id | key   | more_values
------------------------
 1 | SET_A | xxx_1
 2 | SET_A | xxx_2
 3 | SET_B | yyy_1
 4 | SET_C | zzz_1
 5 | SET_C | zzz_2

上述情况也不例外。

MY_TABLE
id | key_from_other_table | some_values
---------------------------------------
 1 | SET_A                | xxx
 2 | SET_B                | yyy
 3 | SET_A                | zzz

OTHER_TABLE
id | key   | more_values
------------------------
 1 | SET_A | xxx_1
 2 | SET_A | xxx_2
 3 | SET_B | yyy_1
 4 | SET_C | zzz_1
 5 | SET_C | zzz_2

上述内容在阅读第3 myTable时引起异常。

但是在MY_TABLE中允许相同的键值(即多个MyTable实体可以从OtherTable共享相同的对象),你如何解决这个问题呢?

我听说将fetch模式更改为eager可以解决这个问题,但我更喜欢使用懒惰提取的解决方案,谢谢。

1 个答案:

答案 0 :(得分:1)

首先,对于OneToMany关联,'many'侧的SQL表(即OtherTable)应该有一个指向'one'侧主键的外键(即MyTable)。在你的情况下,这意味着OtherTable应该有一个名为'myTableId'的列,在MyTable中指向'id'。

这将导致ORM:

class MyTable {

    @Id
    private Integer id;

    @OneToMany
    @JoinColumn(name = "myTableId", referencedColumnName = "id")
    List<OtherTable> otherTables;
}

但是,由于您声明单个OtherTable可以是多个MyTable的成员,因此您需要ManyToMany关联。这涉及创建连接表。连接表可能被称为MyTableOtherTable_JT。该表有两个外键列,一个指向MyTable的主键,名为myTableId,另一列指向OtherTable的主键,名为otherTableId。

这将导致ORM:

class MyTable {

    @Id
    private Integer id;

    @ManyToMany
    @JoinTable( 
        name = "MyTableOtherTable_JT"
        joinColumns=@JoinColumn(name = "myTableId", referencedColumnName = "id"),
        inverseJoinColumns=@JoinColumn(name = "otherTableId", referencedColumnName = "id")
    )
    List<OtherTable> otherTables;
}

class OtherTable {

    @Id
    private Integer id;
}