我在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可以解决这个问题,但我更喜欢使用懒惰提取的解决方案,谢谢。
答案 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;
}