有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Hibernate在集合上循环时删除会话

我在LazyInitializationException: failed to lazily initialize a collection of roles, could not initialize proxy - no Session集合上循环时遇到了这个异常。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();
}

当循环到达第三个myTable时,会发生异常,在该循环中,“key_from_other_table”列中的值与collectionOfMyTables集合中任何之前的myTable相同

如果所有myTable对象在“key_from_other_table”列中的值不同,则不会发生异常

例如:

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

在读取第三个myTable时,上述操作导致异常

但如果MY_表中允许相同的键值(即多个MyTable实体可以共享来自OtherTable的相同对象),如何解决这个问题

我听说将fetch模式更改为eager可能会解决这个问题,但我更喜欢使用lazy fetch的解决方案,谢谢


共 (1) 个答案

  1. # 1 楼答案

    首先,对于OneToMany关联,“多”端(即OtherTable)的SQL表应该有一个外键,指向“一”端(即MyTable)的主键。在您的例子中,这意味着OtherTable应该有一个名为“myTableId”的列,它指向MyTable中的“id”

    这将导致ORM本身:

    class MyTable {
    
        @Id
        private Integer id;
    
        @OneToMany
        @JoinColumn(name = "myTableId", referencedColumnName = "id")
        List<OtherTable> otherTables;
    }
    

    但是,由于您声明一个OtherTable可以是多个MyTables的成员,因此需要一个多个关联。这涉及到创建一个联接表。联接表可以称为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;
    }