【发布时间】:2017-05-18 20:44:13
【问题描述】:
我有两个具有单向关系的父子实体
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;
}
和幼儿园的孩子其实是这样的
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 部分。不幸的是,我还不清楚其中的原因。更改参数不是选项,因为我想使用指向子对象父级的现有链接。
【问题讨论】:
-
你不能使用 JPA Cascade.DELETE stackoverflow.com/questions/19626535/…
-
我认为您的意思是 CascadeType.REMOVE。如果您删除父级,这将不起作用。我想要的是,当您删除父级时,所有子级也会被删除。
-
刚刚检查了来源。 MySQLDialect 覆盖 supportCascadeDelete 以返回 false,这告诉生成器不要将其添加到约束中。您可以向 Hibernate 团队提出拉取请求,但他们添加它可能是有原因的。有时语法被列为受支持,然后您会收到“尚未实现”错误。它发生在我试图在 Oracle 11g 数据库中使用数组时。谁知道从哪个版本开始它实际工作。
-
除了检查方言属性外,
org.hibernate.tool.schema.internal.StandardForeignKeyExporter.getSqlCreateStrings(ForeignKey, Metadata)中还有一个额外的检查,如果第二个条件为真,它只会附加“删除级联”。您可以在此处设置断点并回溯以查看未附加的原因。查看源代码应该是正确的,但是如果@OnDelete(action = OnDeleteAction.CASCADE)设置为您所拥有的。见org.hibernate.cfg.AnnotationBinder.processElementAnnotations(...) -
我已经针对 MySQL5 进行了测试,当且仅当它是单向的 @ManyToOne 关系时,它才能正常工作,而你说你有。 MySQL5InnoDBDialect 肯定会被选中吗?您设置的属性是 Spring Boot 特定的。这是一个 Spring Boot 项目,因为您的问题没有用 Spring Boot 标记?
标签: mysql hibernate spring-boot spring-data jpa-2.1