web-dev-qa-db-ja.com

ManyToManyと複合主キーおよび注釈のマッピング:

複合主キーを使用して、学生と教育コースの間にたくさんの現実を作り出そうとしています:

私のクラス:

@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

何が悪いのですか?

18
danny.lesnik

私はこの問題を解決しました。フィールドの代わりにゲッターをマッピングしました。

public class StudentTClass {

    //@EmbeddedId
    private StudentTClassPK pk = new StudentTClassPK();

    @EmbeddedId
    public StudentTClassPK getPk() {
        return pk;
    }
13
danny.lesnik

可能であれば、複合キーを削除することを強くお勧めします。単純な主キーを使用することで、多くの問題を解消し、コードを簡略化できます。データベースを変更する機能がなかったため、過去にデータベースで複合キーを使用しました。残念ながら、私はコードを持っていません。しかし、すべてを正しく機能させるには、ある程度の作業が必要だったことを覚えています。これ以上は役に立ちません。

5
drekka