我有两个实体,父亲和孩子,它们之间存在单向关系。
在application.properties文件中,我已经配置好了。
幼儿园中的“Child with Kindergarten”实际上是这样的。
class Parent {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
}
并且
class Child {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
@ManyToOne(optional = false)
@JoinColumn(name = "parent_id")
@OnDelete(action = OnDeleteAction.CASCADE)
private Parent parent;
}
在application.properties文件中,我已经配置好了。
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.database-platform = org.hibernate.dialect.MySQL5InnoDBDialect
但是当我运行应用程序时,会创建以下语句
...
alter table child add constraint FKi62eg01ijyk2kya7eil2gafmx foreign key (parent_id) references parent (id)
...
因此,没有像应该有的ON CASCADE DELETE。每次运行应用程序时都会创建表,我检查了该方法。
org.hibernate.dialect.MySQL5InnoDBDialect#supportsCascadeDelete()
这真的叫做(就是这样)。 我正在使用spring-boot-parent版本1.4.3,它使用Hibernate 5.11。 有什么想法吗? 顺便说一下,我不想使用双向关系。
编辑 感谢@AlanHay,我发现我遗漏了一个重要部分。 实际上还涉及第三个类。
class Kindergarten {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "kindergarten", fetch = FetchType.EAGER)
@MapKeyJoinColumn(name = "parent_id") // parent_id causes the problem!
private Map<Parent, Child> children;
}
幼儿园中的“Child with Kindergarten”实际上是这样的。
class Child {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
@ManyToOne(optional = false)
@JoinColumn(name = "parent_id")
@OnDelete(action = OnDeleteAction.CASCADE)
private Parent parent;
@ManyToOne
@JoinColumn(name = "kindergarten_id")
private Kindergarten kindergarten;
}
这就是问题发生的原因。如果你在MapKeyJoinColumn注释中将"parent_id"更改为Child中不存在的列,例如"map_id",则ON DELETE CASCADE将添加到Child中的外键parent_id。如果参数是Child的列"parent_id",那么ON DELETE CASCADE部分将不会被附加。不幸的是,我还不清楚其中的原因。更改参数不是一个选择,因为我想使用现有的链接来连接子对象的父对象。
OneToMany
注释并添加orphanRemoval = true
。这应该确保通过EntityManager.remove()
或 JPQL 查询执行的删除也会删除子实体。但是,如果您使用本机查询删除父实体,则不会删除子实体。 - coladictorg.hibernate.tool.schema.internal.StandardForeignKeyExporter.getSqlCreateStrings(ForeignKey, Metadata)
中还有一个额外的检查,只有在第二个条件为真时才会附加 'on delete cascade'。您可以在此设置断点并跟踪以查看为什么未附加。查看源代码,它应该是正确的,但是如果设置了@OnDelete(action = OnDeleteAction.CASCADE)
,则为真。请参见org.hibernate.cfg.AnnotationBinder.processElementAnnotations(...)
。 - Alan Hay