JPA (с Play!) Двунаправленный «многие ко многим» - как убрать с обеих сторон отношения? - PullRequest
1 голос
/ 18 мая 2011

У меня есть следующее отображение в моей игре!приложение, использующее JPA:

@Entity
public class Contact extends Model {        
    public String name;

    @ManyToMany(mappedBy = "contacts", fetch = FetchType.EAGER)
    public Set<Category> categories = new HashSet<Category>();

    public void addCategory(Category c) {
        this.categories.add(c);
        if (!c.contacts.contains(this)) {
            c.contacts.add(this);
        }
    }

    @PreRemove
    public void preRemove() {
        for (Category c : this.categories) {
            c.contacts.remove(this);
        }
        this.categories = null;
    }
}

@Entity
public class Category extends Model {
    public String name;

    @ManyToMany
    public Set<Contact> contacts = new HashSet<Contact>();

    public void addContact(Contact c) {
        this.contacts.add(c);
        if (!c.categories.contains(this)) {
            c.categories.add(this);
        }
    }

    @PreRemove
    protected void preRemove() {
        for (Contact c : this.contacts) {
            c.categories.remove(this);
        }
        this.contacts = null;
    }
}

Удаление категории работает нормально, отношения обновляются корректно.Однако, если я удаляю контакт, я получаю нарушение ограничения:

Caused by: org.h2.jdbc.JdbcBatchUpdateException: Referential integrity constraint violation: "FK34B085DF487AF903: 
PUBLIC.CATEGORY_CONTACT FOREIGN KEY(CONTACTS_ID) REFERENCES PUBLIC.CONTACT(ID)"; SQL statement:
delete from Contact where id=? [23003-149]

Как я могу гарантировать, что удаление контакта не приведет к удалению категории, а только удалит связь?

РЕДАКТИРОВАТЬ : Дух!Проблема заключалась в том, что у меня также был объект User, который имел ссылки как на контакт, так и на категорию.Я пропустил прояснение этих отношений.Ниже приведено изменение метода preRemove () в классе контактов:

@PreRemove
public void preRemove() {
    for (Category c : this.categories) {
        c.contacts.remove(this);
    }

    this.user.contacts.remove(this);
    for (Category c : this.user.categories) {
        c.contacts.remove(this);
    }
    //It's important to save the user 
    this.user.save();
}

1 Ответ

1 голос
/ 07 ноября 2013

Другое решение заключается в том, чтобы вручную удалить элементы из списка и сохранить его перед удалением основного объекта:

while( !contact.categories.isEmpty() ) {  
    contact.categories.remove(0);  
}  
contact.save();  
contact.delete();
...