java - eclipselink (JPA) 异常 : composite primary key @JoinColumn

标签 java mysql jpa eclipselink

我的天哪!我一直在弄清楚如何解决以下问题。我用谷歌搜索并尝试了所有可能的方法,但没有成功。

Caused by: Exception [EclipseLink-30005] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.PersistenceUnitLoadingException
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: sun.misc.Launcher$AppClassLoader@93dee9
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [RateProfessorPU] failed.
Internal Exception: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The @JoinColumns on the annotated element [field professorId] from the entity class [class rateprofessor.database.entity.Rating] is incomplete. When the source entity class uses a composite primary key, a @JoinColumn must be specified for each join column using the @JoinColumns. Both the name and the referencedColumnName elements must be specified in each such @JoinColumn.
    at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:127)
    at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:115)
    at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source)
    at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source)
    at rateprofessor.database.DBFactory.<clinit>(DBFactory.java:27)
    ... 2 more


我正在使用 netbeans 和 eclipselink (jpa 2.0)。 我附上两个表结构。
对于 Professor 表,name 和 departmentID 是复合主键,id 是自动生成的唯一键,它是评分表的外键。

enter image description here

以下是两个表的 java 类:

教授

@Entity
@Table(name = "professor", catalog = "rateprofessor", schema = "", uniqueConstraints = {
    @UniqueConstraint(columnNames = {"id"})})
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Professor.findAll", query = "SELECT p FROM Professor p"),
    @NamedQuery(name = "Professor.findByName", query = "SELECT p FROM Professor p WHERE p.professorPK.name = :name"),
    @NamedQuery(name = "Professor.findByDepartmentID", query = "SELECT p FROM Professor p WHERE p.professorPK.departmentID = :departmentID"),
    @NamedQuery(name = "Professor.findByEmail", query = "SELECT p FROM Professor p WHERE p.email = :email"),
    @NamedQuery(name = "Professor.findByPhone", query = "SELECT p FROM Professor p WHERE p.phone = :phone"),
    @NamedQuery(name = "Professor.findByTitle", query = "SELECT p FROM Professor p WHERE p.title = :title"),
    @NamedQuery(name = "Professor.findById", query = "SELECT p FROM Professor p WHERE p.id = :id"),
    @NamedQuery(name = "Professor.findByFirstName", query = "SELECT p FROM Professor p WHERE p.firstName = :firstName"),
    @NamedQuery(name = "Professor.findByLastName", query = "SELECT p FROM Professor p WHERE p.lastName = :lastName")})
public class Professor implements Serializable {
    private static final long serialVersionUID = 1L;
    @EmbeddedId
    protected ProfessorPK professorPK;
    @Column(name = "email", length = 255)
    private String email;
    @Column(name = "phone", length = 255)
    private String phone;
    @Basic(optional = false)
    @Column(name = "title", nullable = false, length = 255)
    private String title;
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    private int id;
    @Column(name = "firstName", length = 45)
    private String firstName;
    @Column(name = "lastName", length = 45)
    private String lastName;
    @JoinColumn(name = "departmentID", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
    @ManyToOne(optional = false)
    private Department department;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "professorId")
    private Collection<Rating> ratingCollection;

    public Professor() {
    }

    public Professor(ProfessorPK professorPK) {
        this.professorPK = professorPK;
    }

    public Professor(ProfessorPK professorPK, String title, int id) {
        this.professorPK = professorPK;
        this.title = title;
        this.id = id;
    }

    public Professor(String name, int departmentID) {
        this.professorPK = new ProfessorPK(name, departmentID);
    }

    public ProfessorPK getProfessorPK() {
        return professorPK;
    }

    public void setProfessorPK(ProfessorPK professorPK) {
        this.professorPK = professorPK;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getId() {
        return id;
    }

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

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    @XmlTransient
    public Collection<Rating> getRatingCollection() {
        return ratingCollection;
    }

    public void setRatingCollection(Collection<Rating> ratingCollection) {
        this.ratingCollection = ratingCollection;
    }

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

    @Override
    public String toString() {
        return "rateprofessor.database.entity.Professor[ professorPK=" + professorPK + " ]";
    }

}

评分

@Entity
@Table(name = "rating", catalog = "rateprofessor", schema = "")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Rating.findAll", query = "SELECT r FROM Rating r"),
    @NamedQuery(name = "Rating.findById", query = "SELECT r FROM Rating r WHERE r.id = :id"),
    @NamedQuery(name = "Rating.findByDatetime", query = "SELECT r FROM Rating r WHERE r.datetime = :datetime"),
    @NamedQuery(name = "Rating.findByClass1", query = "SELECT r FROM Rating r WHERE r.class1 = :class1"),
    @NamedQuery(name = "Rating.findBySection", query = "SELECT r FROM Rating r WHERE r.section = :section")})
public class Rating implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    private Integer id;
    @Basic(optional = false)
    @Column(name = "datetime", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date datetime;
    @Column(name = "class", length = 45)
    private String class1;
    @Column(name = "section")
    private Integer section;
    @JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false)
    @ManyToOne(optional = false)
    private User userId;
    @JoinColumn(name = "grade", referencedColumnName = "id")
    @ManyToOne
    private Grade grade;
    @JoinColumn(name = "comment_id", referencedColumnName = "id", nullable = false)
    @ManyToOne(optional = false)
    private Comment commentId;
    @JoinColumn(name = "professor_id", referencedColumnName = "id", nullable = false)
    @ManyToOne(optional = false)
    private Professor professorId;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "rating")
    private Collection<RatingItem> ratingItemCollection;

    public Rating() {
    }

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

    public Rating(Integer id, Date datetime) {
        this.id = id;
        this.datetime = datetime;
    }

    public Integer getId() {
        return id;
    }

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

    public Date getDatetime() {
        return datetime;
    }

    public void setDatetime(Date datetime) {
        this.datetime = datetime;
    }

    public String getClass1() {
        return class1;
    }

    public void setClass1(String class1) {
        this.class1 = class1;
    }

    public Integer getSection() {
        return section;
    }

    public void setSection(Integer section) {
        this.section = section;
    }

    public User getUserId() {
        return userId;
    }

    public void setUserId(User userId) {
        this.userId = userId;
    }

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    public Comment getCommentId() {
        return commentId;
    }

    public void setCommentId(Comment commentId) {
        this.commentId = commentId;
    }

    public Professor getProfessorId() {
        return professorId;
    }

    public void setProfessorId(Professor professorId) {
        this.professorId = professorId;
    }

    @XmlTransient
    public Collection<RatingItem> getRatingItemCollection() {
        return ratingItemCollection;
    }

    public void setRatingItemCollection(Collection<RatingItem> ratingItemCollection) {
        this.ratingItemCollection = ratingItemCollection;
    }

    @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 Rating)) {
            return false;
        }
        Rating other = (Rating) 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 "rateprofessor.database.entity.Rating[ id=" + id + " ]";
    }

}

请帮帮我。我真的需要帮助。非常感谢。

最佳答案

问题是 JPA 不允许您拥有指向非目标实体 ID 字段的字段的外键。在您的情况下,Rating 有一个 professor_id 列,它是 Id 的外键,但 Id 不是主键 - embeddedId 中的 name 和 departmentID 是。最简单的解决方案是将教授中的 ID 字段设置为 ID - 无论如何就 JPA 而言。表本身不需要更改。

这将允许您使用 professor_id 作为 Professor ID 列的外键并在 JPA 提供者之间保持可移植性,并且仍然使用 Name + departmentID 作为数据库中的 pk。

关于java - eclipselink (JPA) 异常 : composite primary key @JoinColumn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8640672/

相关文章:

javascript - 创建一个将文本转换为 Json 文件的网站

java - 在同步方法中将字符串存储在 ArrayList 中

java - 学习调试

javascript - 在 AngularJS 中使用过滤器更新给定的表

java - Spring Data JPA 中的 FetchMode 是如何工作的

java - Android 如何更改电影大小 GIF

Mysql请求返回未定义

mysql - 如何创建页面来编辑数据库

javax.validation.Validation 多重实例化与重用单个 Validator 实例

java - 如何使用 jpa 从数据库中删除单向、一对一映射