Spring Data JPA Quick Guide
  • Spring Data JPA 快速指南
  • 配置依赖
  • 配置数据源
  • 数据库编码与词语定序
  • Core Concepts
  • 基本用法
  • Transactions
    • 什么是事务
    • 配置事务(@EnableTransactionManagement)
    • 配置事务(XML)
    • 配置事务(@Transactional)
    • @Transactional 实现细节
    • Transaction and Spring Data JPA
    • 事务隔离
    • 事务传播
  • Query Creation from Method Names
  • Using @Query
  • Sorting and Pagination
  • Projection
  • Specification
  • Query by Example
  • javax.persistence Annotations
    • @OneToOne (bidirectional)
      • Usage
      • PO Serialization
      • Save and Update
      • Nested Projection
      • @MapsId
    • @OneToMany (bidirectional)
    • @OneToMany (unidirectional)
    • @ManyToMany (bidirectional)
      • Many-to-Many Using a Composite Key
由 GitBook 提供支持
在本页
  1. javax.persistence Annotations
  2. @ManyToMany (bidirectional)

Many-to-Many Using a Composite Key

student
student_course
course

id (PK) name

student_id (PK, FK) course_id (PK, FK) rating

id (PK) name

如上,现在我们希望在中间表加上一个 rating 属性,以表示某学生对某课程的评价。

很明显,上一小节谈到的 Basic Many-to-Many 是没有能力做到这一点的,简单地打上 @ManyToMany 注解并不能在中间表中加上自定义属性。

这就是为什么我们需要 Compositing Key (组合键)。

Spring Data JPA 实现组合键:

@Embeddable
@Getter
@Setter
class CourseRatingKey implements Serializable {
    @Column(name = "student_id")
    private Long studentId;

    @Column(name = "course_id")
    private Long courseId;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CourseRatingKey that = (CourseRatingKey) o;
        return Objects.equals(studentId, that.studentId) && Objects.equals(courseId, that.courseId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(studentId, courseId);
    }
}

一个组合键类必须满足:

  • 标记为 @Embeddable

  • 实现 java.io.Serializable

  • 必须实现 equals() 和 hashCode() 两个方法

  • 实例域中不能出现实体类型

使用组合键:

中间表:

@Entity
@Getter
@Setter
class CourseRating {
    @EmbeddedId
    private CourseRatingKey id;

    @ManyToOne
    @MapsId("studentId")
    @JoinColumn(name = "student_id")
    private Student student;

    @ManyToOne
    @MapsId("courseId")
    @JoinColumn(name = "course_id")
    private Course course;

    int rating;
}
  • @EmbeddedId 用于标记主键。

  • @MapsId 将 student 和 course 的 id 映射到主键(在这里是组合键)中去。

    我们之所以要用 @MapsId 是因为,刚刚提到的,组合键的实例域中不能出现实体类型。

接下来配置 student 和 course:

@Entity
@Getter
@Setter
public class Course {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "course")
    private Set<CourseRating> courseRating;
}
@Entity
@Getter
@Setter
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "student")
    private Set<CourseRating> courseRatings;
}

配置完成。

上一页@ManyToMany (bidirectional)

最后更新于3年前