I've got two tables, b
and a
:
a
has a foreign key to b
that defines this relationship a
, and a JPA @ID
b
when a
is deleteda
's b_id
is NOT NULL
The problem is that when I delete my A
object with JPA repository, I get a ConstraintViolationException
on its foreign key. I would expect that both a
and b
rows are deleted (cleverly starting with a
's one).
How could I work around this knowing that I want to keep:
a
to b
b
id being the JPA @Id
for 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;
}
@Entity
@Table(name = "b")
public class B {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "dbid")
private Integer id;
@OneToOne(mappedBy = "b")
private A a;
}
[EDIT] After all discussions in answer comments and re-reading my question, the proposals with orphanRemoval
indeed are in scope and work.
If you want to delete object of B
, whenever the associated A
is deleted (it's the fourt point of your wishlist:
I want a cascade removal that deletes the related
b
whena
is deleted
then you need to change your mapping in A
to:
@OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true)
@PrimaryKeyJoinColumn
private B b;
In terms of just the MySQL side of your implementation , the records in table B have no 'knowledge' of any record in table A. In the database the relationship is unidirectional
The native cascade functionality exists to prevent foreign key errors, by telling the DB what to do when deleting a record would leave a foreign key pointing nowhere. Deleting a table A record would not cause a foreign key error in any table B records, so any native cascade functionality would not be triggered
To reiterate; You cannot keep the schema the same, and the cascade removal from a
to b
, because you don't actually have the cascade removal from a
to b
You also mentioned in the comments that some table B records can exist without a table A records which isn't in the original question
To obtain the automatic deletion of table B records you describe, you have a few options with regards to the DB:
There may be something in JPA that solves your dilemma out of the box, but under the hood it will be doing one of the above (not option 1 and probably option 4)
In order to achieve what you have asked, I have tweaked your tables as follows:
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
wasn't added in your DDL.
This will enable cascade delete. To delete the b
record on deletion of a
I made following changes in class 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;
}
That worked well. I hope it helps.
Find link here to the working solution .
Can you try in class B to add the following
@OneToOne(mappedBy = "b", cascade = CascadeType.REMOVE)
private A a;
In addition, if in the database you have only a foreign key "a has a foreign key to b" can you also make a foreign key from b to a as well.
try with below code -
@OneToOne(mappedBy = "b",cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval=true )
private A a;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.