java - 无法使用 Hibernate 删除具有@OneToMany 关系的父 JPA 实体

标签 java hibernate jpa jakarta-ee eclipselink

在使用 Hibernate 删除与子实体具有 @OneToMany 关系的 JPA 实体时,我遇到了一个问题,但是当使用 EclipseLink 而不是 Hibernate 作为 JPA 时,相同的代码工作正常提供商。父实体上的注解是@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, orphanRemoval=true)

当使用 Hibernate 时,它​​会尝试将子实体上的连接列设置为 null,但由于该列不允许 null 而失败。使用 EclipseLink 时,它会先删除子实体,然后再删除所需行为的父实体。

我的问题是:

  1. 为什么 Hibernate 和 EclipseLink 的行为不同?据我了解,JPA2 中的 orphanRemovalCascaseType.REMOVE 功能对于两个提供程序的功能应该相同。
  2. 在删除父实体时,我是否可以更改我的代码以允许 EclipseLink 和 Hibernate 发挥相同的作用,而无需先删除子实体?一个约束是代码必须与两个 JPA 提供程序一起工作。

我在 SO 上发现了几个类似的问题,但是其中大部分要么与 JPA 1.0 相关,使用贬值的 Hibernate 注释,要么建议在 @OneToMany 上设置 orphanRemoval=true > 注释。

我使用的 Hibernate 版本是 4.3.10.Final,EclipseLink 的版本是 2.5.2。

为了演示这个问题,我创建了以下相对简单的示例。

父实体的代码如下:

@Entity
@Table(name="HOUSE")
public class HouseEntity {

    @Id
    @Column(name="HOUSE_ID")
    private int houseId;

    @Column(name="HOUSE_NAME")
    private String houseName;

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, orphanRemoval=true)
    @JoinColumn(name = "HOUSE_ID", referencedColumnName = "HOUSE_ID")
    private List<RoomEntity> rooms;

    //Getters, setters, equals, and hashCode omitted
}

子实体的代码如下:

@Entity
@Table(name="ROOM")
public class RoomEntity {

    @Id
    @Column(name="ROOM_ID")
    private int roomId;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "HOUSE_ID", referencedColumnName = "HOUSE_ID")
    private HouseEntity house;

    @Column(name="ROOM_NAME")
    private String roomName;

    //Getters, setters, equals, and hashCode omitted
}

用于删除父实体的EJB代码如下:

@Stateless
public class HouseService {

    @PersistenceContext
    private EntityManager em;

    public void deleteHouse(int houseId) {
        HouseEntity houseEntity = em.find(HouseEntity.class, houseId);
        em.remove(houseEntity);
    }
}

在 Hibernate 中,对数据库执行以下 SQL 语句 update ROOM set HOUSE_ID=null where HOUSE_ID=? 失败并返回 ORA-01407: cannot update ("TEST"."ROOM"."HOUSE_ID") to NULL

在EclipseLink中,先执行SQL语句DELETE FROM ROOM WHERE (HOUSE_ID = ?),然后执行SQL语句DELETE FROM HOUSE WHERE (HOUSE_ID = ?) .

最佳答案

尝试以下操作

@Entity
@Table(name="HOUSE")
public class HouseEntity {

    @Id
    @Column(name="HOUSE_ID")
    private int houseId;

    @Column(name="HOUSE_NAME")
    private String houseName;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "house", cascade = CascadeType.ALL)
    private List<RoomEntity> rooms;

    //Getters, setters, equals, and hashCode omitted
}


@Entity
@Table(name="ROOM")
public class RoomEntity {

    @Id
    @Column(name="ROOM_ID")
    private int roomId;

    @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "HOUSE_ID", referencedColumnName = "HOUSE_ID", nullable = false)
    private HouseEntity house;

    @Column(name="ROOM_NAME")
    private String roomName;

    //Getters, setters, equals, and hashCode omitted
}

关于java - 无法使用 Hibernate 删除具有@OneToMany 关系的父 JPA 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34821895/

相关文章:

java - 抽象类泛型通过构造函数继承

java - 如何对多行字符串进行子串并使用 indexOf

java - Spring 测试 - WebTestClient 无法 Autowiring 。未找到 'WebTestClient' 类型的 beans

java - Hibernate - FetchType.LAZY 急切地加载数据

java - 如何在应用程序级别缓存复杂的java对象

java - 如何在java中组合来自不同数组的元素?

C#让电脑进入休眠或 hibernate 状态

java - JPA 更改不会保留在数据库中

java - Hibernate 实体管理器即使在刷新/刷新后也不会删除对象

java - Spring Data JPA 保存新实体并获取其所有依赖项