複合主キーを使用して、学生と教育コースの間にたくさんの現実を作り出そうとしています:
私のクラス:
@Entity
@Table(name="Student_mtm_cId")
public class Student {
private String id;
private Set<StudentTClass> teachingClasses = new HashSet<StudentTClass>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.student")
public Set<StudentTClass> getTeachingClasses() {
return teachingClasses;
}
public void setTeachingClasses(Set<StudentTClass> teachingClasses) {
this.teachingClasses = teachingClasses;
}
public void addStudentToClass(TeachingClass teachingClass){
StudentTClass studentTClass = new StudentTClass();
studentTClass.setStudent(this);
studentTClass.setTeachingClass(teachingClass);
teachingClasses.add(studentTClass);
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Id @GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
@Column(name = "student_id", nullable = false)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//all other setters and getters and isequal/hashCode omitted.
}
TeachingClass:
@Entity
@Table(name="TechingClass_MTM")
public class TeachingClass {
private String id;
private String name;
private String description;
private Set<StudentTClass> teachingClasses = new HashSet<StudentTClass>();
public TeachingClass(){}
public TeachingClass(String name, String description) {
super();
this.name = name;
this.description = description;
}
public void addStudentToClass(Student student){
StudentTClass studentTClass = new StudentTClass();
studentTClass.setStudent(student);
studentTClass.setTeachingClass(this);
teachingClasses.add(studentTClass);
}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.teachingClass")
public Set<StudentTClass> getTeachingClasses() {
return teachingClasses;
}
public void setTeachingClasses(Set<StudentTClass> teachingClasses) {
this.teachingClasses = teachingClasses;
}
public void setDescription(String description) {
this.description = description;
}
@Id @GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
@Column(name = "teachingClass_id", nullable = false)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
コレクションオブジェクト:
@Entity
@Table(name = "student_TClass_MTM")
@AssociationOverrides({
@AssociationOverride(name = "pk.student", joinColumns = @JoinColumn(name = "student_id")),
@AssociationOverride(name = "pk.teachingClass", joinColumns = @JoinColumn(name = "teachingClass_id"))
})
public class StudentTClass {
@EmbeddedId
private StudentTClassPK pk = new StudentTClassPK();
public StudentTClassPK getPk() {
return pk;
}
public void setPk(StudentTClassPK pk) {
this.pk = pk;
}
public StudentTClass() {}
@Transient
public Student getStudent(){
return this.pk.getStudent();
}
@Transient
public TeachingClass getTeachingClass(){
return this.pk.getTeachingClass();
}
public void setStudent(Student student){
this.pk.setStudent(student);
}
public void setTeachingClass(TeachingClass teachingClass){
this.pk.setTeachingClass(teachingClass);
}
}
今主キー:
@Embeddable
public class StudentTClassPK implements Serializable{
private static final long serialVersionUID = -7261887879839337877L;
private Student student;
private TeachingClass teachingClass;
@ManyToOne
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
@ManyToOne
public TeachingClass getTeachingClass() {
return teachingClass;
}
public void setTeachingClass(TeachingClass teachingClass) {
this.teachingClass = teachingClass;
}
public StudentTClassPK(Student student, TeachingClass teachingClass) {
this.student = student;
this.teachingClass = teachingClass;
}
public StudentTClassPK() {}
}
学生を永続化しようとすると、次のエラーが発生しました。
Caused by: org.hibernate.MappingException: Could not determine type for: com.Vanilla.objects.Student, at table: student_TClass_MTM, for columns: [org.hibernate.mapping.Column(student)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.Java:306)
at org.hibernate.Tuple.PropertyFactory.buildStandardProperty(PropertyFactory.Java:143)
at org.hibernate.Tuple.component.ComponentMetamodel.<init>(ComponentMetamodel.Java:68)
at org.hibernate.mapping.Component.buildType(Component.Java:184)
at org.hibernate.mapping.Component.getType(Component.Java:177)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.Java:290)
at org.hibernate.mapping.RootClass.validate(RootClass.Java:236)
at org.hibernate.cfg.Configuration.validate(Configuration.Java:1362)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.Java:1865)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.Java:855)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.Java:774)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.Java:211)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.Java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1417)
... 51 more
何が悪いのですか?
私はこの問題を解決しました。フィールドの代わりにゲッターをマッピングしました。
public class StudentTClass {
//@EmbeddedId
private StudentTClassPK pk = new StudentTClassPK();
@EmbeddedId
public StudentTClassPK getPk() {
return pk;
}
可能であれば、複合キーを削除することを強くお勧めします。単純な主キーを使用することで、多くの問題を解消し、コードを簡略化できます。データベースを変更する機能がなかったため、過去にデータベースで複合キーを使用しました。残念ながら、私はコードを持っていません。しかし、すべてを正しく機能させるには、ある程度の作業が必要だったことを覚えています。これ以上は役に立ちません。