我在账户和交易之间有一个双向的一对多。
@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "account", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Transaction> transactions = new ArrayList<>();
...
}
@Entity
public class Transaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
@ManyToOne
@JoinColumn(name = "ACCOUNT_ID")
private Account account;
...
}
外键定义了ON DELETE CASCADE约束。
alter table transaction
add constraint FK6
foreign key (account_id)
references account(id) on delete cascade;
但是,当删除一个 "账户 "记录时 为什么hibernate会逐一删除相关的 "事务 "记录呢?
acidTest(entityManager -> {
Account _account = entityManager.find(Account.class, pk);
assertThat(_account.getTransactions().size(), is(2));
});
acidTest(entityManager -> {
Account account = entityManager.find(Account.class, 1L);
entityManager.remove(account);
});
日志:
09:17:56.216 [main] DEBUG c.l.hibernate.JPATxBoundedTest - [TX: begin -->
Hibernate:
select
account0_.id as id1_0_0_,
...
from
account account0_
where
account0_.id=?
09:17:56.223 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [5]
Hibernate:
select
transactio0_.account_id as account_4_14_0_,
transactio0_.id as id1_14_0_,
...
from
transaction transactio0_
where
transactio0_.account_id=?
09:17:56.230 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [5]
Hibernate:
delete from transaction where id=?
09:17:56.241 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [14]
Hibernate:
delete from transaction where id=?
09:17:56.245 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [16]
Hibernate:
delete from account where id=?
09:17:56.249 [main] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [5]
09:17:56.260 [main] DEBUG c.l.hibernate.JPATxBoundedTest - <-- end: TX]
我以为hibernate会跳过删除 "transaction",因为我没有在account -> transactions关系上指定CascadeType.REMOVE。什么情况?
(添加CascadeType.REMOVE也触发了同一组SQL)
@OneToMany(mappedBy = "account", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@org.hibernate.annotations.OnDelete(
action = org.hibernate.annotations.OnDeleteAction.CASCADE)
private List<Transaction> transactions = new ArrayList<>();
spring.jpa.hibernate.ddl-auto=none