Spring JPA OneToOne FK 作为 PK Cascade.Remove

我有两张桌子,b并且a

  • 它们具有一对一的双向关系

  • a有一个外键来b定义这种关系

  • 这个外键也被认为是a, 和 JPA的主键@ID

  • 我想要一个级联删除,删除相关的b何时a被删除

  • 在 MySQL 中,a'sb_idNOT NULL

问题是当我A使用 JPA 存储库删除我的对象时,我会ConstraintViolationException在其外键上得到一个。我希望ab行都被删除(巧妙地从a's 开始)。

知道我想保留,我怎么能解决这个问题:

  • 我的数据库架构相同

  • a从到的级联删除b

  • idb是 JPA@Ida

CREATE TABLE `b` (

  `dbid` int(11) NOT NULL AUTO_INCREMENT,

  PRIMARY KEY (`dbid`),

);


CREATE TABLE `a` (

  `b_id` int(11) NOT NULL,

  KEY `b_fk` (`b_id`),

  CONSTRAINT `b_fk` FOREIGN KEY (`b_id`) REFERENCES `b` (`dbid`),

);


@Entity

@Table(name = "a")

public class A {


    @Id

    @Column(name = "b_id")

    @GeneratedValue(generator = "gen")

    @GenericGenerator(name = "gen", strategy = "foreign", parameters = @Parameter(name="property", value="b"))

    private Integer bId;


    @OneToOne(cascade = CascadeType.REMOVE)

    @PrimaryKeyJoinColumn

    private B b;

}

@Entity

@Table(name = "b")

public class B {


    @Id

    @GeneratedValue(strategy= GenerationType.IDENTITY)

    @Column(name = "dbid")

    private Integer id;


    @OneToOne(mappedBy = "b")

    private A a;

}

[编辑] 在回答评论和重新阅读我的问题的所有讨论之后,这些提案orphanRemoval确实在范围和工作中。


潇湘沐
浏览 120回答 3
3回答

凤凰求蛊

如果您想删除 的对象B,只要关联的对象A被删除(这是您的愿望清单的第四点:我想要一个级联删除,删除相关的b何时a被删除那么您需要将映射更改A为:@OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true) @PrimaryKeyJoinColumn private B b;

holdtom

就您实现的 MySQL 方面而言,表 B 中的记录对表 A 中的任何记录都没有“知识”。在数据库中,关系是单向的存在本机级联功能以防止外键错误,通过告诉数据库在删除记录时要做什么会使外键无处指向。删除表 A 记录不会导致任何表 B 记录中的外键错误,因此不会触发任何本机级联功能重申;您不能保持模式相同,并且从ato级联删除b,因为您实际上没有从ato级联删除b您还在评论中提到,一些表 B 记录可以存在而没有表 A 记录,而表 A 记录不在原始问题中要获得您描述的表 B 记录的自动删除,您有几个关于数据库的选项:交换关系- 删除当前外键并在表 B 中添加一个可以为空的外键列,该列引用表 A 的主键。然后您可以在此外键上进行级联删除。对于不“属于”表 A 记录的表 B 记录,保持新列为空。您还可以向此列添加唯一索引以确保一对一关系添加数据库触发器- 删除表 A 记录时,添加删除引用的表 B 记录的数据库触发器添加一个 DB 过程- 添加一个过程,删除表 A 记录,然后依次删除引用的表 B 记录,可能在事务中。继续前进,仅使用该过程删除表 A 记录不要在 DB 层面解决问题- 与选项 3 基本相同,但将过程逻辑从 DB 层移到应用程序逻辑中JPA 中可能有一些东西可以开箱即用地解决您的困境,但在幕后它将执行上述操作之一(不是选项 1,可能是选项 4)

白板的微信

为了实现您的要求,我对您的表格进行了如下调整:    CREATE TABLE b (       dbid INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY    );    CREATE TABLE a (        b_id int(11) NOT NULL PRIMARY KEY REFERENCES b(dbid) ON DELETE CASCADE    );CASCADE DELETE没有添加到您的 DDL 中。这将启用级联删除。要删除删除b记录,a我在课堂上做了以下更改A:@Entity@Table(name = "a")public class A {    @Id    @Column(name = "b_id")    @GeneratedValue(generator = "gen")    @GenericGenerator(name = "gen", strategy = "foreign", parameters = @Parameter(name="property", value="b"))    private Integer bId;    @OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true)    @PrimaryKeyJoinColumn    private B b;}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java