java JPA + Hibernate:如何定义具有 ON DELETE CASCADE 的约束

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14875793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 17:42:58  来源:igfitidea点击:

JPA + Hibernate: How to define a constraint having ON DELETE CASCADE

javamysqlhibernatejpacascade

提问by toytoy

I am just wondering if there's such a way that I can have build my MySQL table as

我只是想知道是否有一种方法可以将我的 MySQL 表构建为

ALTER TABLE `USERINFO`
  ADD CONSTRAINT `FK_USER_ID` FOREIGN KEY (`USERID`) REFERENCES `USERACCOUNT` (`USERID`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE;

However, I only got this in my DDL when hibernate ++ jpa starts to build my table having "<property name="hibernate.hbm2ddl.auto" value="create" />"

但是,当 hibernate ++ jpa 开始构建具有“ <property name="hibernate.hbm2ddl.auto" value="create" />”的表时,我才在 DDL 中得到了这个

ALTER TABLE `USERINFO` ADD CONSTRAINT `FK_USER_ID` FOREIGN KEY (`USERID`) REFERENCES `USERACCOUNT` (`USERID`);

In my classes, I have these annotation setup,

在我的课程中,我有这些注释设置,

// UserAcc.java
@Entity
@Table(name = "USERACC")
public class UserAcc implements Serializable {

private static final long serialVersionUID = -5527566248002296042L;

@Id
@Column(name = "USERID")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer userId;


@OneToOne(mappedBy = "userAcc")
private UserInfo userInfo;
....


public UserInfo getUserInfo() {
    return userInfo;
}
public void setUserInfo(UserInfo userInfo) {
    this.userInfo = userInfo;
}
...

and,

和,

// UserInfo.java
@Entity
@Table(name = "USERINFO")
public class UserInfo implements Serializable {

private static final long serialVersionUID = 5924361831551833717L;

@Id
@Column(name = "USERINFO_ID", nullable=false)
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer userInfoId;

@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name="USERID", nullable=false)
@ForeignKey(name = "FK_USER_ID")
private UserAcc userAcc;


public Integer getUserInfoId() {
    return userInfoId;
}

public void setUserInfoId(Integer userInfoId) {
    this.userInfoId = userInfoId;
}
...

Note that, UserAccount table is the parent/main table here while UserInfo is an extended table normalize to another entity. Any answers would be greatly appreciated. I'm just curious how it's done as I love to work also in MySQL. I am just really used to deleting a record from the parent table (USERACOUNT) which would would also allow me to cascade a delete thru child records dependent on the specific record from a parent/primary table.

请注意,UserAccount 表是此处的父/主表,而 UserInfo 是一个扩展表,将其标准化为另一个实体。任何答案将不胜感激。我只是好奇它是如何完成的,因为我也喜欢在 MySQL 中工作。我只是真的习惯于从父表 (USERACOUNT) 中删除一条记录,这也将允许我通过依赖于父/主表中的特定记录的子记录级联删除。

Thanks!

谢谢!

回答by Mikko Maunu

JPA does offer possibility to cascadeoperations (merge, persist, refresh, remove) to associated entities. Logic is in JPA and does not utilize database cascades.

JPA 确实提供了将操作(合并、持久化、刷新、删除)级联到关联实体的可能性。逻辑在 JPA 中,不使用数据库级联。

@OneToMany(cascade=CascadeType.REMOVE)

There is no JPA standard compliant way to do cascades with database cascades. If such a cascades are preferred, we have to fall back to Hibernate specific construct: @OnDelete. It works with @OneToManyat least, but there used to be some problems in the past with @OneToOneand @OnDelete.

没有符合 JPA 标准的方法来与数据库级联进行级联。如果喜欢这样的级联,我们必须回退到 Hibernate 特定的构造:@OnDelete。它@OneToMany至少适用于,但过去使用@OneToOne和 时曾经存在一些问题@OnDelete

@OnDelete(action = OnDeleteAction.CASCADE)

Be aware that adding this annotation to an existing constraint will not update it. You may have to manually drop it first to properly update the schema.

请注意,将此注释添加到现有约束不会更新它。您可能必须先手动删除它才能正确更新架构。

回答by cmd

There is no clean cut means to do this in JPA. The following will get you what you want... You can use CascadeType.DELETE, however this annotation only applies to the objects in the EntityManager, not the database. You want to be sure that ON DELETE CASCADEis added to the database constraint. To verify, you can configure JPA to generate a ddl file. Take a look at the ddlfile, you'll notice that ON DELETE CASCADEis not part of the constraint. Add ON DELETE CASCADEto actual SQL in the ddlfile, then update your database schema from the ddl. This will fix your problem .

在 JPA 中没有明确的方法来做到这一点。以下内容将为您提供所需的内容...您可以使用CascadeType.DELETE,但是此注释仅适用于 中的对象EntityManager,而不适用于数据库。您要确保将ON DELETE CASCADE其添加到数据库约束中。要验证,您可以配置 JPA 以生成 ddl 文件。查看ddl文件,您会注意到它ON DELETE CASCADE不是约束的一部分。添加ON DELETE CASCADEddl文件中的实际 SQL ,然后从 ddl 更新您的数据库架构。这将解决您的问题。

This linkshows how to use ON DELETE CASCADEon for CONSTRAINTin MySQL. You do this on the constraint. You can also do it in a CREATE TABLEor ALTER TABLEstatement. It's likely that JPA creates the constraint in an ALTER TABLEstatement. Simply add ON DELETE CASCADEto that statement.

链接显示了如何在 MySQL 中使用ON DELETE CASCADEfor CONSTRAINT。您在约束上执行此操作。您也可以在CREATE TABLEorALTER TABLE语句中执行此操作。JPA 很可能在ALTER TABLE语句中创建了约束。只需添加ON DELETE CASCADE到该语句中即可。

Note that some JPA implementors do provide a means for this functionality.

请注意,某些 JPA 实现者确实为此功能提供了一种方法。

Lastly, Hibernate does supply this functionality using the OnDelete(action = OnDeleteAction.CASCADE)annotation.

最后,Hibernate 确实使用OnDelete(action = OnDeleteAction.CASCADE)注解提供了这个功能。

回答by Alex Torson

You can use Hibernate annotation org.hibernate.annotations@OnDelete(action = OnDeleteAction.CASCADE)on UserAcc.userInfo:

您可以使用Hibernate标注org.hibernate.annotations@OnDelete(action = OnDeleteAction.CASCADE)UserAcc.userInfo

public class UserAcc implements Serializable {

...

@OneToOne(mappedBy = "userAcc")
@OnDelete(action = OnDeleteAction.CASCADE)
private UserInfo userInfo;

...

this will generate DDL ON DELETE CASCADEon foreign key in UserInfotable.

这将ON DELETE CASCADEUserInfo表中的外键上生成 DDL 。