When not using generics, ensure the target entity

2019-09-13 23:20发布

问题:

I new to JPA and learn from http://uaihebert.com/jpa-manytomany-unidirectional-and-bidirectional/

I have created two tables, one is Person and another is Notebook. If not mistaken, person_has_notebook will be created if the code run successfully. (Correct me if I'm wrong as I am new to JPA).

Person

   @Entity
@Table(name = "Person")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p")
    , @NamedQuery(name = "Person.findById", query = "SELECT p FROM Person p WHERE p.id = :id")
    , @NamedQuery(name = "Person.findByName", query = "SELECT p FROM Person p WHERE p.name = :name")
    , @NamedQuery(name = "Person.findByCompName", query = "SELECT p FROM Person p WHERE p.compName = :compName")})
public class Person implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @Column(name = "Name")
    private String name;
    @Basic(optional = false)
    @Column(name = "CompName")
    private String compName;

    @ManyToMany
    @JoinTable(name="person_has_notebooks", joinColumns={@JoinColumn(name="person_id")}, inverseJoinColumns={@JoinColumn(name="notebook_id")})
    private List notebooks;

    public List getNotebooks() {
        return notebooks;
    }

    public void setNotebooks(List notebooks) {
        this.notebooks = notebooks;
    }

    public Person() {
    }

    public Person(Integer id) {
        this.id = id;
    }

    public Person(Integer id, String name, String compName) {
        this.id = id;
        this.name = name;
        this.compName = compName;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCompName() {
        return compName;
    }

    public void setCompName(String compName) {
        this.compName = compName;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.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 Person)) {
            return false;
        }
        Person other = (Person) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "entity.Person[ id=" + id + " ]";
    }

}

NoteBook

 @Entity
@Table(name = "NoteBook")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "NoteBook.findAll", query = "SELECT n FROM NoteBook n")
    , @NamedQuery(name = "NoteBook.findById", query = "SELECT n FROM NoteBook n WHERE n.id = :id")
    , @NamedQuery(name = "NoteBook.findBySerialName", query = "SELECT n FROM NoteBook n WHERE n.serialName = :serialName")
    , @NamedQuery(name = "NoteBook.findByRam", query = "SELECT n FROM NoteBook n WHERE n.ram = :ram")
    , @NamedQuery(name = "NoteBook.findByHd", query = "SELECT n FROM NoteBook n WHERE n.hd = :hd")})
public class NoteBook implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @Column(name = "SerialName")
    private String serialName;
    @Basic(optional = false)
    @Column(name = "Ram")
    private int ram;
    @Basic(optional = false)
    @Column(name = "HD")
    private int hd;

    @ManyToMany(mappedBy="notebooks")
    private List person;

    public List getPersons() {
        return person;
    }

    public void setPersons(List persons) {
        this.person = persons;
    }

    public NoteBook() {
    }

    public NoteBook(Integer id) {
        this.id = id;
    }

    public NoteBook(Integer id, String serialName, int ram, int hd) {
        this.id = id;
        this.serialName = serialName;
        this.ram = ram;
        this.hd = hd;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getSerialName() {
        return serialName;
    }

    public void setSerialName(String serialName) {
        this.serialName = serialName;
    }

    public int getRam() {
        return ram;
    }

    public void setRam(int ram) {
        this.ram = ram;
    }

    public int getHd() {
        return hd;
    }

    public void setHd(int hd) {
        this.hd = hd;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.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 NoteBook)) {
            return false;
        }
        NoteBook other = (NoteBook) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "entity.NoteBook[ id=" + id + " ]";
    }

}

ManyToMany1

public class ManyToMany1 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("ManyToMany1PU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        NoteBook noteA = new NoteBook();
        noteA.setSerialNumber("A0123");
        NoteBook noteB = new NoteBook();
        noteB.setSerialNumber("B0123");
        NoteBook noteC = new NoteBook();
        noteC.setSerialNumber("C0123");

        List notebooks = new ArrayList();
        notebooks.add(noteA);
        notebooks.add(noteB);
        notebooks.add(noteC);

        Person person = new Person();
        person.setName("Zorro");
        person.setNotebooks(notebooks);

        em.persist(person);

        em.getTransaction().commit();

    }

}

Error

Exception Description: Predeployment of PersistenceUnit [ManyToMany1PU] failed.
Internal Exception: Exception [EclipseLink-7214] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The target entity of the relationship attribute [notebooks] on the class [class entity.Person] cannot be determined.  When not using generics, ensure the target entity is defined on the relationship mapping.
    at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:127)
    at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactoryImpl(PersistenceProvider.java:107)
    at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:177)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
    at manytomany1.ManyToMany1.main(ManyToMany1.java:27)

I have assigned mappedBy to the weak side, but why still getting such errors ?

回答1:

Why not just use generics as the message tells you?

@ManyToMany
@JoinTable(name="person_has_notebooks", joinColumns={@JoinColumn(name="person_id")}, inverseJoinColumns={@JoinColumn(name="notebook_id")})
private List<NoteBook> notebooks;

and

@ManyToMany(mappedBy="notebooks")
private List<Person> person;


回答2:

As the error states, when not using generics, you have to tell the provider which Entity you are referring to. Neil Stockton's answer below has an example of how to use generics. The javadoc has an example of specifying the target entity if you can't or don't want to use generics, as JPA has no idea what class you are referring to otherwise.

@ManyToMany(targetEntity=com.example.NoteBook.class)
@JoinTable(name="person_has_notebooks", joinColumns={@JoinColumn(name="person_id")}, inverseJoinColumns={@JoinColumn(name="notebook_id")})
private List notebooks;

@ManyToMany(mappedBy="notebooks", targetEntity=com.example.Person.class)
private List person;

Otherwise, if you can use generics in the List, use Neils answer.



标签: java jpa mapping