在休眠状态下保留具有复合主键的1-m实体

时间:2015-05-11 14:47:22

标签: java hibernate jpa orm hibernate-mapping

我与Mentor to Students的实体之间的关系低于1米。导师有复合主键,我在学生中用作外键

@Entity
public class Mentor implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    private MentorPK id;
    private String email;
    @OneToMany(mappedBy="mentor")
    private Set<Student> students;

    public MentorPK getId() {
        return id;
    }            
    //getters and setters
}

@Embeddable
public class MentorPK implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    private String add;
    //getters and setters
    //override equals and hashcode
}


@Entity
public class Student implements Serializable{
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
    private String name;    

    @ManyToOne
    @MapsId("id")
    @JoinColumns({
        @JoinColumn(name="name_fk", referencedColumnName="name"),
        @JoinColumn(name="address_fk", referencedColumnName="address")
    })
    private Mentor mentor;

    //Getters and setters
}

然后我坚持上面的内容如下,但只有导师在学生桌空的地方持续存在。

如何与学生一起坚持导师?

Set<Student> students = new HashSet<Student>();

Student s1 = new Student();
s1.setName("Student 1");

Student s2 = new Student();
s2.setName("Student 2");

students.add(s1);
students.add(s2);

MentorPK mpk = new MentorPK();
mpk.setAddress("C");
mpk.setName("D");

Mentor m = new Mentor();
m.setId(mpk);
m.setEmail("emaill");
m.setStudents(students);

studentManager.saveMentor(m);

5 个答案:

答案 0 :(得分:2)

尝试将学生字段的注释更改为

@OneToMany(mappedBy="mentor", cascade = CascadeType.PERSIST)

答案 1 :(得分:2)

当您使用复合键时,映射为Embeddable,您需要使用@EmbeddedId

@Entity
public class Mentor {

    @EmbeddedId
    private MentorPK id;

    private String email;
    @OneToMany(mappedBy="mentor")
    private Set<Student> students;

    public MentorPK getId() {
        return id;
    }            
    //getters and setters
}

并且学生变成:

@Entity
public class Student {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
    private String name;    

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="name_fk", referencedColumnName="name"),
        @JoinColumn(name="address_fk", referencedColumnName="address")
    })
    private Mentor mentor;

    //Getters and setters
}

@MapsId@Id共享相同的数据库列时使用@ManyToOne,这不是您的情况,因为您有一个数字标识符和一个复合外键

答案 2 :(得分:2)

您可能需要在每位学生中创建从学生到导师的参考。

因此,在您的代码中,创建m后,您需要:

s1.setMentor(m);
s2.setMentor(m);

否则,Hibernate可能不知道用{。{1}}和name_fk填充列的内容。

答案 3 :(得分:1)

如何改变:

ng-style

为:

@OneToMany(mappedBy="mentor")
private Set<Student> students;

@OneToMany(mappedBy="mentor")
private Set<Student> students = new HashSet();

也尽量不要跳过

@OneToMany(cascade=CascadeType.ALL)
 @JoinColumn(name="student_id")
@org.hibernate.annotations.IndexColumn(name="idx") 
private Set<Student> students = new HashSet();

部分

答案 4 :(得分:1)

据我了解您的要求,您希望Mentor成为该关系的所有者。您没有使用行@OneToMany(mappedBy="mentor")获取此信息。这实际上将学生作为关系的所有者。

我测试了这个域模型,并对注释做了一些修改,以使测试代码按预期工作。

<强>学生

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private int id;
    private String name;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name="name_fk", referencedColumnName="name", insertable = false, updatable = false),
            @JoinColumn(name="address_fk", referencedColumnName="address", insertable = false, updatable = false )
    })
    private Mentor mentor;

//setters and getters
}

<强>明导

public class Mentor implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    private MentorPK id;
    private String email;
    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumns({
            @JoinColumn(name="name_fk", referencedColumnName="name"),
            @JoinColumn(name="address_fk", referencedColumnName="address")
    })
    private Set<Student> students;
//setters and getters
}

它甚至无需执行:s1.setMentor(m);s2.setMentor(m);。我没想到它,但似乎hibernate正在处理这个问题。

相关文章为here

注意:在更改注释后删除数据库表,以便允许hibernate重新创建表。