我有两个表,b
和a
:
a
具有b
的外键,用于定义这种关系a
和JPA @ID
的主键b
时删除相关的a
a
的{{1}}是b_id
问题是,当我使用JPA存储库删除NOT NULL
对象时,我在其外键上得到了A
。
我希望同时删除ConstraintViolationException
和a
行(最好从b
的行开始)。
在知道自己想保留的情况下,我该如何解决:
a
到a
的级联删除b
ID为b
的JPA @Id
a
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;
}
[EDIT]在回答了所有答案并重新阅读了我的问题之后,带有@Entity
@Table(name = "b")
public class B {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "dbid")
private Integer id;
@OneToOne(mappedBy = "b")
private A a;
}
的提案确实在范围和工作中。
答案 0 :(得分:1)
如果您想删除B
的对象,则只要删除关联的A
(这就是您的愿望清单的关键点:
我想要一个级联删除,以便在删除
b
时删除相关的a
然后,您需要将A
中的映射更改为:
@OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true)
@PrimaryKeyJoinColumn
private B b;
答案 1 :(得分:1)
为了实现您的要求,我对您的表格进行了如下调整:
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;
}
效果很好。希望对您有所帮助。
在此处找到指向有效的solution的链接。
答案 2 :(得分:1)
仅从实现的MySQL方面来看,表B中的记录没有表A中任何记录的“知识”。在数据库中,关系是单向的
存在本机级联功能以防止外键错误,方法是通过告诉DB删除记录时该怎么做将使外键指向无处。删除表A记录不会在任何表B记录中引起外键错误,因此不会触发任何本机级联功能
重申; 您无法保持架构相同,也无法将级联从a
移至b
,因为实际上并没有级联从a
移至b
您还在评论中提到,某些表B记录可以不存在原始问题中的表A记录而存在
要获得您描述的表B记录的自动删除,关于数据库,您有几个选择:
JPA中可能有一些解决方案可以立即解决您的难题,但是在幕后,它将执行上述操作之一(不是选项1,可能是选项4)
答案 3 :(得分:0)
您可以在B类中尝试添加以下内容吗?
@OneToOne(mappedBy = "b", cascade = CascadeType.REMOVE)
private A a;
此外,如果在数据库中您只有一个外键“ a有一个到b的外键”,那么您也可以从b到a都有一个外键。
答案 4 :(得分:0)
尝试以下代码-
@OneToOne(mappedBy = "b",cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval=true )
private A a;