已为此查找操作错误地提供了空 PK 的实例

An instance of a null PK has been incorrectly provided for this find operation

我正在使用 Eclipselink 将数据保存到 MySQL 数据库,当我调用创建方法时,它给我错误:

An instance of a null PK has been incorrectly provided for this find operation

我在这里搜索了其他问题,但其中 none 解决了我的问题。 我有一个 class Autor 和一个 class Filme。两者的 ID 字段都是 AUTO INCREMENT 并且 table Filme 具有引用 Autor.id_autor.

的外键

这是我的数据库的代码:


CREATE TABLE `autor` (
  `id_autor` int(11) NOT NULL AUTO_INCREMENT,
  `nome` varchar(100) NOT NULL,
  PRIMARY KEY (`id_autor`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

CREATE TABLE `filme` (
  `id_filme` int(11) NOT NULL AUTO_INCREMENT,
  `id_autor` int(11) NOT NULL,
  `nome` varchar(100) NOT NULL,
  PRIMARY KEY (`id_filme`),
  KEY `fk_flme_ator_idx` (`id_autor`),
  CONSTRAINT `fk_flme_ator` FOREIGN KEY (`id_autor`) REFERENCES `autor` (`id_autor`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

和 Java classes:

Autor.java

package model;

import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@Entity
@Table(name = "autor")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Autor.findAll", query = "SELECT a FROM Autor a"),
    @NamedQuery(name = "Autor.findByIdAutor", query = "SELECT a FROM Autor a WHERE a.idAutor = :idAutor"),
    @NamedQuery(name = "Autor.findByNome", query = "SELECT a FROM Autor a WHERE a.nome = :nome")})
public class Autor implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id_autor")
    private Integer idAutor;
    @Basic(optional = false)
    @Column(name = "nome")
    private String nome;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "idAutor")
    private Collection<Filme> filmeCollection;

    public Autor() {
    }

    public Autor(Integer idAutor) {
        this.idAutor = idAutor;
    }

    public Autor(Integer idAutor, String nome) {
        this.idAutor = idAutor;
        this.nome = nome;
    }

    public Integer getIdAutor() {
        return idAutor;
    }

    public void setIdAutor(Integer idAutor) {
        this.idAutor = idAutor;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @XmlTransient
    public Collection<Filme> getFilmeCollection() {
        return filmeCollection;
    }

    public void setFilmeCollection(Collection<Filme> filmeCollection) {
        this.filmeCollection = filmeCollection;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (idAutor != null ? idAutor.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Autor)) {
            return false;
        }
        Autor other = (Autor) object;
        if ((this.idAutor == null && other.idAutor != null) || (this.idAutor != null && !this.idAutor.equals(other.idAutor))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return nome;
    }
    
}

Filme.java

package model;

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

@Entity
@Table(name = "filme")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Filme.findAll", query = "SELECT f FROM Filme f"),
    @NamedQuery(name = "Filme.findByIdFilme", query = "SELECT f FROM Filme f WHERE f.idFilme = :idFilme"),
    @NamedQuery(name = "Filme.findByNome", query = "SELECT f FROM Filme f WHERE f.nome = :nome")})
public class Filme implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id_filme")
    private Integer idFilme;
    @Basic(optional = false)
    @Column(name = "nome")
    private String nome;
    @JoinColumn(name = "id_autor", referencedColumnName = "id_autor")
    @ManyToOne(optional = false)
    private Autor idAutor;

    public Filme() {
    }

    public Filme(Integer idFilme) {
        this.idFilme = idFilme;
    }

    public Filme(Integer idFilme, String nome) {
        this.idFilme = idFilme;
        this.nome = nome;
    }

    public Integer getIdFilme() {
        return idFilme;
    }

    public void setIdFilme(Integer idFilme) {
        this.idFilme = idFilme;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Autor getIdAutor() {
        return idAutor;
    }

    public void setIdAutor(Autor idAutor) {
        this.idAutor = idAutor;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (idFilme != null ? idFilme.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Filme)) {
            return false;
        }
        Filme other = (Filme) object;
        if ((this.idFilme == null && other.idFilme != null) || (this.idFilme != null && !this.idFilme.equals(other.idFilme))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return nome;
    }

}

Main.java:

public static void main(String[] args) {

        EntityManagerFactory emf = null;
        if (emf == null) {
            emf = Persistence.createEntityManagerFactory("Estudos_JPAPU");
        }
        
        Autor a = new Autor();
        a.setNome("Autor 1");
        a.setFilmeCollection(new ArrayList());
        
        Filme f = new Filme();
        f.setNome("Filme 1");
        f.setIdAutor(a);

        a.getFilmeCollection().add(f);
                
        new AutorJpaController(emf).create(a);

    }

编辑

AutorJpaController.java

import controller.exceptions.IllegalOrphanException;
import controller.exceptions.NonexistentEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import model.Filme;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import model.Autor;

public class AutorJpaController implements Serializable {

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

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

    public void create(Autor autor) {
        if (autor.getFilmeCollection() == null) {
            autor.setFilmeCollection(new ArrayList<Filme>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Collection<Filme> attachedFilmeCollection = new ArrayList<Filme>();
            for (Filme filmeCollectionFilmeToAttach : autor.getFilmeCollection()) {
                filmeCollectionFilmeToAttach = em.getReference(filmeCollectionFilmeToAttach.getClass(), filmeCollectionFilmeToAttach.getIdFilme());
                attachedFilmeCollection.add(filmeCollectionFilmeToAttach);
            }
            autor.setFilmeCollection(attachedFilmeCollection);
            em.persist(autor);
            for (Filme filmeCollectionFilme : autor.getFilmeCollection()) {
                Autor oldIdAutorOfFilmeCollectionFilme = filmeCollectionFilme.getIdAutor();
                filmeCollectionFilme.setIdAutor(autor);
                filmeCollectionFilme = em.merge(filmeCollectionFilme);
                if (oldIdAutorOfFilmeCollectionFilme != null) {
                    oldIdAutorOfFilmeCollectionFilme.getFilmeCollection().remove(filmeCollectionFilme);
                    oldIdAutorOfFilmeCollectionFilme = em.merge(oldIdAutorOfFilmeCollectionFilme);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Autor autor) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Autor persistentAutor = em.find(Autor.class, autor.getIdAutor());
            Collection<Filme> filmeCollectionOld = persistentAutor.getFilmeCollection();
            Collection<Filme> filmeCollectionNew = autor.getFilmeCollection();
            List<String> illegalOrphanMessages = null;
            for (Filme filmeCollectionOldFilme : filmeCollectionOld) {
                if (!filmeCollectionNew.contains(filmeCollectionOldFilme)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Filme " + filmeCollectionOldFilme + " since its idAutor field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Collection<Filme> attachedFilmeCollectionNew = new ArrayList<Filme>();
            for (Filme filmeCollectionNewFilmeToAttach : filmeCollectionNew) {
                filmeCollectionNewFilmeToAttach = em.getReference(filmeCollectionNewFilmeToAttach.getClass(), filmeCollectionNewFilmeToAttach.getIdFilme());
                attachedFilmeCollectionNew.add(filmeCollectionNewFilmeToAttach);
            }
            filmeCollectionNew = attachedFilmeCollectionNew;
            autor.setFilmeCollection(filmeCollectionNew);
            autor = em.merge(autor);
            for (Filme filmeCollectionNewFilme : filmeCollectionNew) {
                if (!filmeCollectionOld.contains(filmeCollectionNewFilme)) {
                    Autor oldIdAutorOfFilmeCollectionNewFilme = filmeCollectionNewFilme.getIdAutor();
                    filmeCollectionNewFilme.setIdAutor(autor);
                    filmeCollectionNewFilme = em.merge(filmeCollectionNewFilme);
                    if (oldIdAutorOfFilmeCollectionNewFilme != null && !oldIdAutorOfFilmeCollectionNewFilme.equals(autor)) {
                        oldIdAutorOfFilmeCollectionNewFilme.getFilmeCollection().remove(filmeCollectionNewFilme);
                        oldIdAutorOfFilmeCollectionNewFilme = em.merge(oldIdAutorOfFilmeCollectionNewFilme);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = autor.getIdAutor();
                if (findAutor(id) == null) {
                    throw new NonexistentEntityException("The autor with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Autor autor;
            try {
                autor = em.getReference(Autor.class, id);
                autor.getIdAutor();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The autor with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Collection<Filme> filmeCollectionOrphanCheck = autor.getFilmeCollection();
            for (Filme filmeCollectionOrphanCheckFilme : filmeCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Autor (" + autor + ") cannot be destroyed since the Filme " + filmeCollectionOrphanCheckFilme + " in its filmeCollection field has a non-nullable idAutor field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            em.remove(autor);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Autor> findAutorEntities() {
        return findAutorEntities(true, -1, -1);
    }

    public List<Autor> findAutorEntities(int maxResults, int firstResult) {
        return findAutorEntities(false, maxResults, firstResult);
    }

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

    public Autor findAutor(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Autor.class, id);
        } finally {
            em.close();
        }
    }

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

FilmeJpaController.java

import controller.exceptions.NonexistentEntityException;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import model.Autor;
import model.Filme;

public class FilmeJpaController implements Serializable {

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

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

    public void create(Filme filme) {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Autor idAutor = filme.getIdAutor();
            if (idAutor != null) {
                idAutor = em.getReference(idAutor.getClass(), idAutor.getIdAutor());
                filme.setIdAutor(idAutor);
            }
            em.persist(filme);
            if (idAutor != null) {
                idAutor.getFilmeCollection().add(filme);
                idAutor = em.merge(idAutor);
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Filme filme) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Filme persistentFilme = em.find(Filme.class, filme.getIdFilme());
            Autor idAutorOld = persistentFilme.getIdAutor();
            Autor idAutorNew = filme.getIdAutor();
            if (idAutorNew != null) {
                idAutorNew = em.getReference(idAutorNew.getClass(), idAutorNew.getIdAutor());
                filme.setIdAutor(idAutorNew);
            }
            filme = em.merge(filme);
            if (idAutorOld != null && !idAutorOld.equals(idAutorNew)) {
                idAutorOld.getFilmeCollection().remove(filme);
                idAutorOld = em.merge(idAutorOld);
            }
            if (idAutorNew != null && !idAutorNew.equals(idAutorOld)) {
                idAutorNew.getFilmeCollection().add(filme);
                idAutorNew = em.merge(idAutorNew);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = filme.getIdFilme();
                if (findFilme(id) == null) {
                    throw new NonexistentEntityException("The filme with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Filme filme;
            try {
                filme = em.getReference(Filme.class, id);
                filme.getIdFilme();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The filme with id " + id + " no longer exists.", enfe);
            }
            Autor idAutor = filme.getIdAutor();
            if (idAutor != null) {
                idAutor.getFilmeCollection().remove(filme);
                idAutor = em.merge(idAutor);
            }
            em.remove(filme);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Filme> findFilmeEntities() {
        return findFilmeEntities(true, -1, -1);
    }

    public List<Filme> findFilmeEntities(int maxResults, int firstResult) {
        return findFilmeEntities(false, maxResults, firstResult);
    }

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

    public Filme findFilme(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Filme.class, id);
        } finally {
            em.close();
        }
    }

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

对于创建,根据您希望如何处理对象图,您需要查看该图中的引用并适当地处理它们:

public void create(Filme filme) {
    EntityManager em = null;
    try {
        em = getEntityManager();
        em.getTransaction().begin();
        Autor autor = filme.getIdAutor();
        if (autor != null) {
            Integer autorId = autor.getId();
          if (autorId == null) {
            em.persist(autor);
          } else {
            //if this has an id, let this call throw an error if it doesn't exist in the database
            autor = em.getReference(idAutor.getClass(), autorId);
            filme.setIdAutor(autor);
            //autor is managed already, so no need to call merge
            autor.getFilmeCollection().add(filme);
        }
        em.persist(filme);
        em.getTransaction().commit();
    } finally {
        if (em != null) {
            em.close();
        }
    }
}

以上内容允许您决定在遇到从 Filme 引用 Autor 实例时要做什么。尽管显式调用 Persist 会导致 persist 调用在 filmeCollection 关系上级联,因此其中引用的任何内容也会对其进行 persist 调用 - 如果这不是 blank/empty 实例,则需要注意这一点。