Проблема с контроллером jpa и каскадным удалением - PullRequest
0 голосов
/ 04 октября 2019

У меня есть две таблицы с простым ограничением внешнего ключа, связывающим одну с другой.

Таблица A
id: Long (pk)

Таблица B
id: Long (pk)
a_id: Long (от Fk до таблицы A: id)

Если я удаляю из таблицы A, я хочу, чтобы она каскадно удалялась из таблицы B, поэтомувнешний ключ в таблице A смоделирован, как показано ниже, в сущности JPA

@OneToMany(cascade = CascadeType.ALL, mappedBy = "a_id", orphanRemoval = true)
@CascadeOnDelete
private List<B> bList;

и тот же ключ в таблице B

@JoinColumn(name = "a_id", referencedColumnName = "id")
@ManyToOne(optional = false)
private A a_id;

Однако, когдаКонтроллер jpa генерируется с помощью опции «Новые классы контроллеров JPA из классов сущностей» в NetBeans, он генерирует метод уничтожения, который проверяет потерянные записи и не может уничтожить, если таковые существуют

        List<String> illegalOrphanMessages = null;
        List<B> bListOrphanCheck = a.getBList();
        for (B bListOrphanCheckB : bListOrphanCheck) {
            if (illegalOrphanMessages == null) {
                illegalOrphanMessages = new ArrayList<String>();
            }
            illegalOrphanMessages.add("This A (" + a + ") cannot be destroyed since the B " + bListOrphanCheckB + " in its bList field has a non-nullable a_id field.");
        }

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

спасибо ....

1 Ответ

0 голосов
/ 07 октября 2019

(Это не ответ, это ответ karelss, но он слишком длинный для комментария)

Вот код контроллера, столбец «a_id» в таблице B скомпилирован с именем «aId "во время создания контроллера, но кроме этого никаких других изменений.

package test.controllers;

import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import uk.co.utel.dataaccess.entities.B;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import uk.co.utel.dataaccess.controllers.exceptions.IllegalOrphanException;
import uk.co.utel.dataaccess.controllers.exceptions.NonexistentEntityException;
import uk.co.utel.dataaccess.entities.A;

public class AJpaController implements Serializable {

    public AJpaController(EntityManagerFactory emf) {
    this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
    return emf.createEntityManager();
    }

    public void create(A a) {
    if (a.getBList() == null) {
        a.setBList(new ArrayList<B>());
    }

    EntityManager em = null;
    try {
        em = getEntityManager();
        em.getTransaction().begin();

        List<B> attachedBList = new ArrayList<B>();
        for (B bListBToAttach : a.getBList()) {
        bListBToAttach = em.getReference(bListBToAttach.getClass(), bListBToAttach.getId());
        attachedBList.add(bListBToAttach);
        }
        a.setBList(attachedBList);

        for (B bListB : a.getBList()) {
        A oldAIdOfBListB = bListB.getAId();
        bListB.setAId(a);
        bListB = em.merge(bListB);
        if (oldAIdOfBListB != null) {
            oldAIdOfBListB.getBList().remove(bListB);
            oldAIdOfBListB = em.merge(oldAIdOfBListB);
        }
        }

        em.getTransaction().commit();
    } finally {
        if (em != null) {
        em.close();
        }
    }
    }

    public void edit(A a) throws IllegalOrphanException, NonexistentEntityException, Exception {
    EntityManager em = null;
    try {
        em = getEntityManager();
        em.getTransaction().begin();
        A persistentA = em.find(A.class, a.getId());
        List<B> bListOld = persistentA.getBList();
        List<B> bListNew = a.getBList();

        List<String> illegalOrphanMessages = null;
        for (B bListOldB : bListOld) {
        if (!bListNew.contains(bListOldB)) {
            if (illegalOrphanMessages == null) {
            illegalOrphanMessages = new ArrayList<String>();
            }
            illegalOrphanMessages.add("You must retain B " + bListOldB + " since its aId field is not nullable.");
        }
        }

        if (illegalOrphanMessages != null) {
        throw new IllegalOrphanException(illegalOrphanMessages);
        }

        List<B> attachedBListNew = new ArrayList<B>();
        for (B bListNewBToAttach : bListNew) {
        bListNewBToAttach = em.getReference(bListNewBToAttach.getClass(), bListNewBToAttach.getId());
        attachedBListNew.add(bListNewBToAttach);
        }
        bListNew = attachedBListNew;
        a.setBList(bListNew);

        for (B bListNewB : bListNew) {
        if (!bListOld.contains(bListNewB)) {
            A oldAIdOfBListNewB = bListNewB.getAId();
            bListNewB.setAId(a);
            bListNewB = em.merge(bListNewB);
            if (oldAIdOfBListNewB != null && !oldAIdOfBListNewB.equals(a)) {
            oldAIdOfBListNewB.getBList().remove(bListNewB);
            oldAIdOfBListNewB = em.merge(oldAIdOfBListNewB);
            }
        }
        }

        em.getTransaction().commit();
    } catch (Exception ex) {
        String msg = ex.getLocalizedMessage();
        if (msg == null || msg.length() == 0) {
        Long id = a.getId();
        if (findA(id) == null) {
            throw new NonexistentEntityException("The a with id " + id + " no longer exists.");
        }
        }
        throw ex;
    } finally {
        if (em != null) {
        em.close();
        }
    }
    }

    public void destroy(Long id) throws IllegalOrphanException, NonexistentEntityException {
    EntityManager em = null;
    try {
        em = getEntityManager();
        em.getTransaction().begin();
        A a;
        try {
        a = em.getReference(A.class, id);
        a.getId();
        } catch (EntityNotFoundException enfe) {
        throw new NonexistentEntityException("The a with id " + id + " no longer exists.", enfe);
        }
        List<String> illegalOrphanMessages = null;
        List<B> bListOrphanCheck = a.getBList();
        for (B bListOrphanCheckB : bListOrphanCheck) {
        if (illegalOrphanMessages == null) {
            illegalOrphanMessages = new ArrayList<String>();
        }
        illegalOrphanMessages.add("This A (" + a + ") cannot be destroyed since the B " + bListOrphanCheckB + " in its bList field has a non-nullable aId field.");
        }

        em.remove(a);
        em.getTransaction().commit();
    } finally {
        if (em != null) {
        em.close();
        }
    }
    }

    public List<A> findAEntities() {
    return findAEntities(true, -1, -1);
    }

    public List<A> findAEntities(int maxResults, int firstResult) {
    return findAEntities(false, maxResults, firstResult);
    }

    private List<A> findAEntities(boolean all, int maxResults, int firstResult) {
    EntityManager em = getEntityManager();
    try {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(A.class));
        Query q = em.createQuery(cq);
        if (!all) {
        q.setMaxResults(maxResults);
        q.setFirstResult(firstResult);
        }
        return q.getResultList();
    } finally {
        em.close();
    }
    }

    public A findA(Long id) {
    EntityManager em = getEntityManager();
    try {
        return em.find(A.class, id);
    } finally {
        em.close();
    }
    }

    public int getACount() {
    EntityManager em = getEntityManager();
    try {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        Root<A> rt = cq.from(A.class);
        cq.select(em.getCriteriaBuilder().count(rt));
        Query q = em.createQuery(cq);
        return ((Long) q.getSingleResult()).intValue();
    } finally {
        em.close();
    }
    }

}
...