Реализация JPA (orphanRemoval = true) - PullRequest
2 голосов
/ 20 марта 2019

Я читал сообщения о orphanRemoval= true в JPA.Согласно документации:

orphanRemoval - это флаг -

Применять ли операцию удаления к сущностям, которые были удалены из отношения, и каскадную операцию удаления к этим сущностям.

Также я сослался на эту статью для получения дополнительной информации, где они пытались установить дочернюю сущность (адрес - в их примере) как ноль.

I в настоящее времяпонимать, что выполнение orphanRemoval= true будет выполнять операции, аналогичные cascade=CascadeType.REMOVE и , если я удалю свою родительскую сущность, она также удалит дочернюю сущность.

То, что я хочу проверить, этодополнительные функциональные возможности, которые он приносит, а именно удаление сущностей, на которые не ссылается их родительская сущность.

Я пытаюсь создать аналогичный сценарий, в котором я устанавливаю новую коллекциюномера телефонов new ArrayList<>(), где родительским объектом является Person .

Ниже приведены мои классы объектов.

Person.java

@Entity
@Table(name = "person")
@Data
public class Person {

    @Id
    int pd ;
    String fname;
    String lname;

    @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,mappedBy="person",orphanRemoval=true)
    List<Phone> phones = new ArrayList<>() ;

    public boolean addPhone(Phone phone) {
        boolean added = this.phones.add(phone);
        phone.setPerson(this);
        return added;
    }
}

Phone.java

@Entity
@Table(name = "phone")
@Data
public class Phone {
    private int countryCode;
    @Id
    private String number ;

    @ManyToOne
    @JoinColumn(name="fk_person")
    Person person ;

}

основной класс

public void testFlow() {

    Person p = fetchById(765);      
    p.setPhones(new ArrayList<>());
    personRepo.save(p); **// exception on this line**
    getPersons();
}


public Person fetchById(int id) {

    Optional<Person> pe = personRepo.findById(id);
    Person person = pe.get();
    System.out.println("person is :"+ person.getFname());
    System.out.println("cc is :"+ person.getPhones().get(0).getNumber());   

    return person; 

}

public List<Person> getPersons() {

        List<Person> persons = personRepo.findAll();
        persons.forEach(p -> {
            System.out.println("person :"+p.getPd());
            System.out.println("person phones :"+p.getPhones().get(0).getNumber());
            System.out.println("=================================");
        });
        return persons;
}

Метод ввода: testFlow () .

Когда я выполняю этот код, я получаюошибка:

org.hibernate.HibernateException: на коллекцию с cascade = "all-delete-orphan" больше не ссылался экземпляр владельца объекта: com.example.entity.Person.phones

Любая подсказка, как я могу протестировать рабочий пример orphanRemoval?

Ответы [ 2 ]

2 голосов
/ 20 марта 2019

Проблема вызвана следующей строкой:

p.setPhones(new ArrayList<>());

В Hibernate вы не можете перезаписать коллекцию, извлеченную из контекста персистентности, если для ассоциации задано orphanRemoval = true. Если ваша цель - получить пустую коллекцию, используйте p.getPhones().clear().

1 голос
/ 20 марта 2019

Это строка, которую должно выдать исключение:

personRepo.save(p);

Это происходит потому, что вы пытаетесь сохранить Person, который не ссылается на Phone s.Я имею в виду, что вы разыменовываете только Person, но не Phone сущности.Поскольку это двунаправленные отношения, вам нужно разыменовать оба:

public void testFlow() {
    Person p = fetchById(765);      
    p.getPhones().foreach(ph -> ph.setPerson(null));
    p.setPhones(new ArrayList<>());
    personRepo.save(p); **// exception on this line**
    getPersons();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...