Java 在hibernate中使用复合主键持久化1m实体

Java 在hibernate中使用复合主键持久化1m实体,java,hibernate,jpa,orm,hibernate-mapping,Java,Hibernate,Jpa,Orm,Hibernate Mapping,我在指导学生的实体上有低于1米的关系。导师有复合主键,我用它作为学生的外键 @Entity public class Mentor implements Serializable { private static final long serialVersionUID = 1L; @Id private MentorPK id; private String email; @OneToMany(mappedBy="mentor") private

我在指导学生的实体上有低于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
}
@实体
公共类Mentor实现了可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
私人导师身份证;
私人字符串电子邮件;
@OneToMany(mappedBy=“mentor”)
私立学校学生;
public getId(){
返回id;
}            
//接球手和接球手
}
@可嵌入
公共类实现了可序列化{
私有静态最终长serialVersionUID=1L;
私有字符串名称;
私有字符串添加;
//接球手和接球手
//重写equals和hashcode
}
@实体
公共类学生实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私有int-id;
私有字符串名称;
@许多酮
@MapsId(“id”)
@连接柱({
@JoinColumn(name=“name\u fk”,referencedColumnName=“name”),
@JoinColumn(name=“地址”,referencedColumnName=“地址”)
})
私人导师;
//接球手和接球手
}
然后,我坚持上面的内容,如下所示,但在学生表为空的情况下,只坚持导师

我怎样才能坚持让导师和学生在一起

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);
Set students=newhashset();
学生s1=新学生();
s1.课程名称(“学生1”);
学生s2=新学生();
s2.设置名称(“学生2”);
学生。加上(s1);
学生。添加(s2);
导师PK mpk=新导师PK();
mpk.设置地址(“C”);
mpk.setName(“D”);
导师m=新导师();
m、 setId(mpk);
m、 setEmail(“emaill”);
m、 学生(学生);
学生管理者。saveMentor(m);

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


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

使用复合密钥时,映射为需要使用的可嵌入密钥:

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

如何更改:

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

部分您可能需要在每个学生中创建从学生到导师的参考

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

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

否则Hibernate可能不知道用什么填充列
name\u fk
address\u fk

据我所知,您希望导师成为关系的所有者。您不能通过行
@OneToMany(mappedBy=“mentor”)
获得此信息。这实际上将学生视为关系的所有者

我已经测试了这个域模型,并对注释做了一些修改,以使测试代码如您所期望的那样工作

学生

公共类学生实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私有int-id;
私有字符串名称;
@许多酮
@连接柱({
@JoinColumn(name=“name\u fk”,referencedColumnName=“name”,insertable=false,updateable=false),
@JoinColumn(name=“address\u fk”,referencedColumnName=“address”,insertable=false,updateable=false)
})
私人导师;
//二传手和接球手
}
导师

public类实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
私人导师身份证;
私人字符串电子邮件;
@OneToMany(级联=级联类型.ALL)
@连接柱({
@JoinColumn(name=“name\u fk”,referencedColumnName=“name”),
@JoinColumn(name=“地址”,referencedColumnName=“地址”)
})
私立学校学生;
//二传手和接球手
}
它甚至可以不做任何事情而工作:
s1.setMentor(m);s2.setMentor(m)。我没有预料到,但hibernate似乎正在处理这个问题

相关文章如下


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

添加cascade=CascadeType.PERSIST属性无效。我刚刚使用您提供的代码创建了一个小样本项目(修复地址/添加字段名的不一致性,删除过时的@MapsId注释)并添加级联类型,调用entityManager.persist(m)后,它按预期工作学生们也被持久化了。我刚刚注意到你提到了hibernate,我用eclipselink创建了一个示例。你可能想尝试使用最新版本,如果它仍然对你不起作用,那么检查这是否是一个报告的bug,或者自己报告它。为什么
CascadeType.PERSIST
Cas更受欢迎cadeType。本例中的所有
?基于
导师提供的数据模型
“拥有”他们关联的
学生
,因此有理由期望
删除
操作也会层叠。我想学生拥有这种关系,因为外键驻留在学生侧。我想我必须先坚持学生,然后坚持导师和学生。这实际上是一个i学生Id主键的自动生成问题。你能创建没有导师的学生吗?@DuncanKinnear是的,我是canThank。但实际上我想让学生成为关系的所有者。这就是为什么我把mappedBy放在导师的位置。所以我认为模型是正确的,但我在客户端保存数据的方式是错误的。你能回答这个问题吗为了让学生以正确的方式与导师保持联系,我尝试以下方法:学生s1=新学生();s1.setName(“学生1”);导师PK mpk=新导师PK();mpk.setAddress(“C”);mpk.setName(“D”);导师m=新导师();m.setId(mpk);m.setEmail(“emaill”);s1.setMentor(m);//studentMana
@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();
 = new HashSet();
s1.setMentor(m);
s2.setMentor(m);