java - 在集合上循环时 Hibernate 删除 session

标签 java hibernate jpa

我在 MyTable 集合上循环时遇到此异常 LazyInitializationException:无法延迟初始化角色集合,无法初始化代理 - 无 session 。例如:

@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

以上也不异常(exception)。

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_TABLE 中允许使用相同的键值(即多个 MyTable 实体可以共享 OtherTable 中的相同对象),您如何解决这个问题?

我听说将获取模式更改为 eager 可能会解决此问题,但我更喜欢使用延迟获取的解决方案,谢谢。

最佳答案

首先,对于 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 可以是多个 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;
}

关于java - 在集合上循环时 Hibernate 删除 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49291515/

相关文章:

java - 有什么方法可以让接口(interface)中的方法使用 DAO 模式返回通用 List<> 吗?

java - 将 hibernate 与泛型一起使用

hibernate - @Temporal(TemporalType.DATE) 的问题

java - 使用 UUID 作为 Hibernate 主键 id 是否被认为是糟糕的设计?

java - spring中如何为xml中定义的带有父级的bean选择构造函数?

java - 是否有可能在编译时像禁用 Java 1.4 的 assert 关键字一样禁用 guava 的先决条件?

java - Hibernate <generator class =""> 什么时候最好使用什么?

performance - Spring、JPA (Hibernate) 和 Ehcache 性能不佳

java - 带注释的entitymanager空指针异常

java - 停止 Java 时不执行存储过程