【问题标题】:Spring JPA Cascade.ALL won't delete parent objectSpring JPA Cascade.ALL 不会删除父对象
【发布时间】:2018-08-28 16:14:29
【问题描述】:

我在https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#associations-many-to-many 上关注这个“带有链接实体生命周期的双向多对多”教程。但是,我使用的是 Spring JPA 而不是 Entity Manager。当我使用存储库接口删除地址时,即使我已经级联所有,它也不会删除 PersonAddress 记录。它给了我外键约束异常。

"参照完整性约束违规:"FKCYC1KRSXQELKM4UWH65AVIJ23: PUBLIC.PERSON_ADDRESS FOREIGN KEY(ADDRESS_ID) REFERENCES PUBLIC.ADDRESS(ID) (1)";SQL 语句:"

我的课在下面。

@Entity(name = "Address")
public class Address  {

@Id
@GeneratedValue
private Long id;

private String street;

@Column(name = "number")
private String number;

private String postalCode;

@OneToMany(mappedBy = "address", cascade = {CascadeType.ALL}, orphanRemoval = true, fetch=FetchType.LAZY)
private List<PersonAddress> owners = new ArrayList<>();

PersonAddress.java

 @Entity(name = "PersonAddress")
    public class PersonAddress implements Serializable {

    @Id
    @ManyToOne
    private Person person;

    @Id
    @ManyToOne
    private Address address;

Person.java

@Entity(name = "Person")
public class Person{

    @Id
    @GeneratedValue
    private Long id;

    @NaturalId
    private String registrationNumber;

    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<PersonAddress> addresses = new ArrayList<>();

Person和Address关联后删除地址的测试方法。这应该删除 PersonAddress 中的一条记录,因为 Address 有 Cascade.ALL 但它没有发生。我错过了什么?

@Test
@Transactional
public void testDeleteAddressAfterPatronAdd() {

Person person1 = new Person("ABC-123");
Person person2 = new Person("DEF-456");
Address address1 = new Address("12th Avenue", "12A", "4005A");
Address address2 = new Address("18th Avenue", "18B", "4007B");

Person savedPerson1 = personRepository.save(person1);
Person savedPerson2 = personRepository.save(person2);       
Address savedAddress1 = addressRepository.save(address1);
Address savedAddress2 = addressRepository.save(address2);
personRepository.flush();       
addressRepository.flush();

PersonAddress personAddress1 = new PersonAddress(savedPerson1, savedAddress1);      
PersonAddress personAddress2 = new PersonAddress(savedPerson2, savedAddress2);
savedPerson1.getAddresses().add(personAddress1);
savedPerson2.getAddresses().add(personAddress2);
personRepository.flush();       
addressRepository.flush();

Address loadedAddress1 = addressRepository.findById(savedAddress1.getId());
loadedAddress1.getOwners();
addressRepository.delete(loadedAddress1);       
addressRepository.flush();

【问题讨论】:

    标签: java spring hibernate jpa cascade


    【解决方案1】:

    您没有正确维护关联的两个方面。 personAddress1 引用了 address1,但 address1 在其所有者列表中没有任何元素。

    因此,当您删除 address1 时,Hibernate 不会将删除级联给任何所有者,因为列表中没有任何所有者。并且删除因此失败,因为您试图删除由 PersonAddress 引用的 Address,尽管是 FK 约束。

    【讨论】:

    • 我也应该将 personAddress1 添加到 address1 吗?当我尝试删除当前处于会话中的 address1 对象时,我会遇到这个问题。但是,我正在从数据库中读取地址并执行 getOwners()。不会将所有者从数据库加载到loadedAddress1 中吗?如果我错了,请纠正我,这就是为什么我认为我们已经将地址级联到 PersonAddress。
    • 所有工作都在同一个会话中完成,在调用事务方法时打开,在返回时关闭。所以你没有从这里的数据库中读取任何内容。 findById() 从一级缓存中返回实体,这是您之前保存实体时填充的。
    猜你喜欢
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 2013-07-22
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    相关资源
    最近更新 更多