【问题标题】:Can add extra field(s) to @ManyToMany Hibernate extra table?可以向@ManyToMany Hibernate 额外表添加额外字段吗?
【发布时间】:2010-11-12 07:26:34
【问题描述】:

我有这两个类(表)

@Entity
@Table(name = "course")
public class Course {

    @Id
    @Column(name = "courseid")
    private String courseId;
    @Column(name = "coursename")
    private String courseName;
    @Column(name = "vahed")
    private int vahed;
    @Column(name = "coursedep")
    private int dep;
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "student_course", joinColumns = @JoinColumn(name = "course_id"),  inverseJoinColumns = @JoinColumn(name = "student_id"))
    private Set<Student> student = new HashSet<Student>();
//Some setter and getter

还有这个:

    @Entity
    @Table(name = "student")
    public class Student {

        @Id
        @Column(name="studid")
        private String stId;
        @Column(nullable = false, name="studname")
        private String studName;
        @Column(name="stmajor")
        private String stMajor;
        @Column(name="stlevel", length=3)
        private String stLevel;
        @Column(name="stdep")
        private int stdep;

        @ManyToMany(fetch = FetchType.LAZY)
        @JoinTable(name = "student_course"
                ,joinColumns = @JoinColumn(name = "student_id")
                ,inverseJoinColumns = @JoinColumn(name = "course_id")
        )
        private Set<Course> course = new HashSet<Course>();
//Some setter and getter

运行此代码后,在数据库(student_course)中创建了一个额外的表,现在我想知道如何在此表中添加额外的字段,例如(Grade、Date 和 ...(我的意思是 student_course 表)) 我看到了一些解决方案,但我不喜欢它们,而且我对它们也有一些问题:

First Sample

【问题讨论】:

  • 您可以使用 \@OrderColumn 添加一个额外的列,它是一个 int 列,用于存储 many2many 关系的排序顺序。我希望他们也能添加一个 \@TempolalColumns 来添加一个 fromDate 和 toDate 字段

标签: java hibernate


【解决方案1】:

student_course 表纯粹是为了记录两个实体之间的关联。由hibernate管理,不能包含其他数据。

您要记录的数据类型需要建模为另一个实体。也许您可以在 Course 和 StudentResult(包含成绩等)之间建立一对多关联,然后在 StdentResult 和 Student 之间建立多对一关联。

【讨论】:

    【解决方案2】:

    放弃多对多,创建一个名为 StudentCourseRelationship 的类,并在 Student 和 Course 上设置一对多到 StudentCourseRelationship。

    你可以在上面放各种各样的东西,比如 DateEnrolled、DateKickedOut 等等。

    IMO 多对多映射有点麻烦。

    【讨论】:

    • DateGotToGripsWithAssociations 怎么样? :)
    【解决方案3】:

    如果您在链接表 (STUDENT_COURSE) 上添加额外字段,则必须根据 skaffman 的回答或如下所示的其他方法选择一种方法。

    有一种方法,链接表 (STUDENT_COURSE) 的行为类似于 @Embeddable,根据:

    @Embeddable
    public class JoinedStudentCourse {
    
        // Lets suppose you have added this field
        @Column(updatable=false)
        private Date joinedDate;
    
        @ManyToOne(fetch=FetchType.LAZY)
        @JoinColumn(name="STUDENT_ID", insertable=false, updatable=false)
        private Student student;
    
        @ManyToOne(fetch=FetchType.LAZY)
        @JoinColumn(name="COURSE_ID", insertable=false, updatable=false)
        private Course course;
    
        // getter's and setter's 
    
        public boolean equals(Object instance) {
            if(instance == null)
                return false;
    
            if(!(instance instanceof JoinedStudentCourse))
                return false;
    
            JoinedStudentCourse other = (JoinedStudentCourse) instance;
            if(!(student.getId().equals(other.getStudent().getId()))
                return false;
    
            if(!(course.getId().equals(other.getCourse().getId()))
                return false;
    
            // ATT: use immutable fields like joinedDate in equals() implementation
            if(!(joinedDate.equals(other.getJoinedDate()))
                return false;
    
            return true;
        }
    
        public int hashcode() {
            // hashcode implementation
        }
    
    }
    

    因此您将同时参加学生和课程课程

    public class Student {
    
        @CollectionOfElements
        @JoinTable(
            table=@Table(name="STUDENT_COURSE"),
            joinColumns=@JoinColumn(name="STUDENT_ID")
        )
        private Set<JoinedStudentCourse> joined = new HashSet<JoinedStudentCourse>();
    
    }
    
    public class Course {
    
        @CollectionOfElements
        @JoinTable(
            table=@Table(name="STUDENT_COURSE"),
            joinColumns=@JoinColumn(name="COURSE_ID")
        )
        private Set<JoinedStudentCourse> joined = new HashSet<JoinedStudentCourse>();
    
    }
    

    记住:@Embeddable 类的生命周期绑定到拥有实体类(Student 和 Course),因此请注意它。

    建议:Hibernate 团队支持这两种方法(@OneToMany(skaffman 的回答)或 @CollectionsOfElements),因为 @ManyToMany 映射存在一些限制 - 级联操作。

    问候,

    【讨论】:

    • 很好的答案。如果只需要一个索引列来映射到列表,则可以添加 @OrderColumn
    • 当我尝试上述解决方案时,我得到了Repeated column in mapping for collection 错误。有什么想法吗?
    • 我遇到了与 Ankur Ra​​iyani 相同的错误,我的解决方案是使用 skaffman 解决方案。在 studentcourse 中使用嵌入的 id 来确保我有正确的主键。然后我删除了嵌入的密钥并为每个 manToOne 关系扔了一个@Id
    • @Ankur Ra​​yani 已修复。这是因为 2 个属性 - Student.joined 和 JoinedStudentCourse.student - 管理同一列。 由于 Hibernate 只能管理一个属性,您应该使用 insertable=false, updatable=false 禁用一个属性。同样适用于 Course.joined 和 JoinedStudentCourse.course
    • @Eyad Ebrahim 查看对 Ankur Ra​​yani 评论的回复
    【解决方案4】:

    不幸的是,接受的答案对我不起作用,hibernate 以一种奇怪的方式生成连接表(所有连接列都是重复的)。但是,具有连接表专用实体的变体可以正常工作。这里描述的很详细:http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-04
      • 2015-08-26
      • 2018-10-10
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 2019-12-30
      相关资源
      最近更新 更多