如果定义了@JoinTable,则JPA无法删除@OneToOne

时间:2019-01-10 16:55:47

标签: jpa java-ee one-to-one jointable

我有一个有趣的“问题”,即现象。

快速信息:

  • _BaseEntity@MappedSuperclass,可以处理ID,hashCode,equals,compareTo等,并且在我所有的项目中都能正常工作
  • 我正在MySQL DB上使用Payara(EclipseLink)
  • @Expose GSON 标记
  • 我发现了很多类似的主题,但是没有一个回答我的问题,或者没有/没有@JoinTable还是没有区别,或者没有解决问题的答案...
  • 该关系是单方面的,即仅来自Thema->TopThema,并且明确没有TopThema->Thema

工作示例 当我设置了这样的实体

@Entity
@Table(name = Thema.TABLE_NAME)
public class Thema extends _BaseEntity {
    static public final String TABLE_NAME = UEntity.TABLE_PREFIX + "Thema";

    @Expose @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) 
    private TopThema topThema;
}

我可以简单地 EntityManager.remove()

示例无法正常工作

但是,如果是这样定义的

@Entity
@Table(name = Thema.TABLE_NAME)
public class Thema extends _BaseEntity {
    static public final String TABLE_NAME = UEntity.TABLE_PREFIX + "Thema";

    @Expose @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) 
    @JoinTable(name = TABLE_NAME + "_topThema")
    private TopThema topThema;
}

(具有@JoinTable(name = TABLE_NAME + "_topThema")定义的中间表“ GP_Thema_topThema”,然后 EntityManager.remove()引发异常:

  

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:   无法删除或更新父行:外键约束失败   ({test_PT_localGP_Thema_topThema,约束   FK_GP_Thema_topThema_topThema_ID外键(topThema_ID)   参考文献GP_TopThemaID

我知道使用额外的@JoinTable并没有多大意义,这时引用也可以只保存在“ GP_Thema”中作为“ GP_Thema”。“ TOPTHEMA_ID”。 另外:两种Entity定义在Java方面都可以很好地工作。

但是出于兴趣:为什么即使我设置了@JoinTableGP_Thema_topThema,JPA仍无法删除cascade = CascadeType.ALL orphanRemoval = true中的条目?

更新:由于@JoinTable,我也无法  -首先删除TopThema,然后删除Thema(在TopThema上抛出MySQLIntegrityConstraintViolationException删除)  -det Thema.topThema = null,然后更新(再次抛出MySQLIntegrityConstraintViolationException

2 个答案:

答案 0 :(得分:1)

不是JPA无法删除实体,而是实际数据库。您正在寻找的是可延期的约束,而这在MySQL中是不可能的。

有关可约束的here

的Mysql文档
  

通常,与MySQL一样,在插入,删除或更新许多行的SQL语句中,InnoDB逐行检查UNIQUE和FOREIGN KEY约束。在执行外键检查时,InnoDB在必须查看的子记录或父记录上设置共享的行级锁。 InnoDB立即检查外键约束;该检查不会推迟到事务提交。根据SQL标准,默认行为应推迟检查。也就是说,仅在处理了整个SQL语句之后才检查约束。在InnoDB实现延迟约束检查之前,某些事情是不可能的,例如删除使用外键引用其自身的记录

您是否考虑过切换到PostgreSQL

  

DEFERRED约束直到事务提交才检查

答案 1 :(得分:0)

作为旁注,您可以使用JPA和MySQL删除Thema实体...为此,只需将@JoinTable(GP_Thema_topThema)的外键声明为“ ON DELETE”即可。级联” ...

示例:

CREATE TABLE GP_Thema_topThema(
    thema_ID integer NOT NULL,
    topThema_ID integer NOT NULL,
    FOREIGN KEY (thema_ID)
        REFERENCES thema (id)
        ON DELETE CASCADE,
    FOREIGN KEY (topThema_ID)
        REFERENCES top_thema(id)
        ON DELETE CASCADE
)

这样,如果数据库收到删除Thema实体的命令,那么任何相关的GP_Thema_topThema实体(或元组)也将被删除...