Java 具有多对一关系的复合主键不支持映射错误

Java 具有多对一关系的复合主键不支持映射错误,java,jakarta-ee,servlets,jpa,persistence,Java,Jakarta Ee,Servlets,Jpa,Persistence,我有三个实体,它们通过复合主键和其他表的外键形成关联关系。这些是这些实体的实施: @Entity @Table(name = "STUDENTSCOURSES", schema = "GPA") @NamedQuery(name = "getAllStdCrs", query = "SELECT sc FROM StudentsCourses sc") @IdClass(StudentCourseId.class) public class StudentsCourses implements

我有三个实体,它们通过复合主键和其他表的外键形成关联关系。这些是这些实体的实施:

@Entity
@Table(name = "STUDENTSCOURSES", schema = "GPA")
@NamedQuery(name = "getAllStdCrs", query = "SELECT sc FROM StudentsCourses sc")
@IdClass(StudentCourseId.class)
public class StudentsCourses implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(name="studentID", insertable=false, updatable= false)
private int studentID;  

@Id
@Column(name="crsID", insertable=false, updatable=false)
private int crsID;

@ManyToOne
@JoinColumn(name="STUDENTID")
Student student;

@ManyToOne
@JoinColumn(name="CRSID")
Course course;

public StudentsCourses() {
    super();
}

public void setStudentID(int studentID) {
    this.studentID = studentID;
}
public int getStudentID() {
    return studentID;
}
public void setCrsID(int crsID) {
    this.crsID = crsID;
}
public int getCrsID() {
    return crsID;
}   
}
课程实体:

@Entity
@Table(name = "COURSES", schema = "GPA")
@NamedQuery(name = "getAllCourses", query = "SELECT c FROM Course c")
public class Course implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="CRSID")
private int crsID;
private String name;

@OneToMany(mappedBy="course", fetch=FetchType.LAZY)
private Set<Assesment> assesments;

@OneToMany(mappedBy="course", fetch=FetchType.LAZY)
private Set<StudentsCourses> studentCourses;

public Course() {
    super();
}

public int getCrsID() {
    return crsID;
}

public void setCrsID(int crsID) {
    this.crsID = crsID;
}

public String getName() {
    return name;
}

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

public void setAssesments(Set<Assesment> assesments) {
    this.assesments = assesments;
}

public Set<Assesment> getAssesments() {
    return assesments;
}

public void setStudentCourses(Set<StudentsCourses> studentCourses) {
    this.studentCourses = studentCourses;
}

public Set<StudentsCourses> getStudentCourses() {
    return studentCourses;
}
}
@实体
@表(name=“COURSES”,schema=“GPA”)
@NamedQuery(name=“getAllCourses”,query=“从课程c中选择c”)
公共类课程实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“CRSID”)
私人国际信托投资公司;
私有字符串名称;
@OneToMany(mappedBy=“course”,fetch=FetchType.LAZY)
私有集评估;
@OneToMany(mappedBy=“course”,fetch=FetchType.LAZY)
私人设置的学生课程;
公共课程(){
超级();
}
public int getCrsID(){
返回crsID;
}
公共无效设置crsID(int crsID){
this.crsID=crsID;
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共无效集合评估(集合评估){
此项评估=评估;
}
公共集getAssessments(){
回报评估;
}
公共无效设置学生课程(设置学生课程){
this.studentCourses=studentCourses;
}
公共设置getStudentCourses(){
返回学生课程;
}
}
学生实体:

@Entity
@Table(name = "STUDENTS", schema = "GPA")
@NamedQuery(name = "getAllStudents", query = "SELECT s FROM Student s")
public class Student implements Serializable {


private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int studentID;
private String studentName;

@OneToMany(mappedBy="student", fetch = FetchType.LAZY)
private Set<Assesment> assesments;

@OneToMany(mappedBy="student", fetch = FetchType.LAZY)
private Set<StudentsCourses> studentCourses;

public Student() {
    super();
}

public int getStudnetID() {
    return studentID;
}

public void setStudnetID(int stdID) {
    this.studentID = stdID;
}

public void setStudentName(String studentName) {
    this.studentName = studentName;
}

public String getStudentName() {
    return studentName;
}

public void setAssesments(Set<Assesment> assesments) {
    this.assesments = assesments;
}

public Set<Assesment> getAssesments() {
    return assesments;
}

public void setStudentCourses(Set<StudentsCourses> studentCourses) {
    this.studentCourses = studentCourses;
}

public Set<StudentsCourses> getStudentCourses() {
    return studentCourses;
}
}
@实体
@表(name=“STUDENTS”,schema=“GPA”)
@NamedQuery(name=“getAllStudents”,query=“从学生s中选择s”)
公共类学生实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私立国际学生;
私有字符串studentName;
@OneToMany(mappedBy=“student”,fetch=FetchType.LAZY)
私有集评估;
@OneToMany(mappedBy=“student”,fetch=FetchType.LAZY)
私人设置的学生课程;
公立学生(){
超级();
}
public int getStudnetID(){
返回学生ID;
}
公共无效设置studnetid(int stdID){
this.studentID=stdID;
}
public void setStudentName(字符串studentName){
this.studentName=studentName;
}
公共字符串getStudentName(){
返回学生姓名;
}
公共无效集合评估(集合评估){
此项评估=评估;
}
公共集getAssessments(){
回报评估;
}
公共无效设置学生课程(设置学生课程){
this.studentCourses=studentCourses;
}
公共设置getStudentCourses(){
返回学生课程;
}
}
当我尝试运行该程序时,出现以下错误:

[4/5/13 0:30:15:243 EDT] 00000028 webapp        E com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E: [Servlet Error]-[com.gpa.app.servlet.LoginServlet]: <openjpa-2.1.1-SNAPSHOT-r422266:1141200 fatal user error> org.apache.openjpa.persistence.ArgumentException: Field "com.gpa.app.entities.Course.studentCourses" cannot declare that it is mapped by another field. Its mapping strategy (org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy) does not support mapping by another field.
[4/5/13 0:30:15:243 EDT]00000028 webapp E com.ibm.ws.webcontainer.webapp.webapp logServletError SRVE0293E:[Servlet错误]-[com.gpa.app.Servlet.LoginServlet]:org.apache.openjpa.persistence.ArgumentException:字段“com.gpa.app.enties.Course.studentCourses”不能声明它由另一字段映射。它的映射策略(org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy)不支持其他字段的映射。

问题的原因可能是什么。感谢您的帮助。

所以问题出在我的@Id类中。在那个类中,我没有实现equal和hash代码方法,也没有实现Serializable。做完这件事以后,一切都很顺利。多亏了艾尔克,他给了我尝试不同版本的想法,这帮助我找到了原因

我在中修改的代码如下所示:

public class StudentCourseId implements Serializable{

private static final long serialVersionUID = 1L;
private int studentID;
private int crsID;

public StudentCourseId() {
}

public StudentCourseId(int studentID, int crsID) {
    this.studentID = studentID;
    this.crsID = crsID;
}

public void setStudentID(int studentID) {
    this.studentID = studentID;
}

public int getStudentID() {
    return studentID;
}

public void setCrsID(int crsID) {
    this.crsID = crsID;
}

public int getCrsID() {
    return crsID;
}
public int hashCode() {
    return studentID + crsID;
}

public boolean equals(Object o) {
    return ((o instanceof StudentCourseId)
            && studentID == ((StudentCourseId) o).getStudentID() && crsID == ((StudentCourseId) o)
                .getCrsID());
}
    }
 public int getCrsID() {
    return crsID;
}   
}
希望对将来的人有所帮助

谢谢,
Sas

您正在尝试做的应该是可能的,但我现在没有时间找出问题所在。然而,我想指出的是,StudentCourses看起来非常像一个链接表。因此,StudentCourses实体只在学生和课程之间建立链接。如果这是正确的,您可以省去StudentCourses实体,在学生和课程之间建立直接的多人映射。尝试以下方法:@OneToMany(fetch=FetchType.EAGER,cascade={CascadeType.ALL},orphanRemoving=true)@JoinColumn(name=“columnName”)私有设置StudentCourses@谢谢你的评论。根据我的应用范围,多对多关系不适用。如果我有一个学生在数据库中存在不止一次,我将无法检索一个特定学生的所有课程。是的,我选择了一对多。感谢您的时间。@Neron感谢您的回答,我尝试了您的代码,仍然得到相同的错误。再看一眼,没有发现映射有任何错误。EclipseLink也没有发现它的缺点。我注意到,在错误中,您使用了openjpa的快照版本,也许您应该尝试另一个版本。