[英]Can an entity be updated instead of being inserted using spring-data-jpa when entity ID is not known without issuing a query?
[英]Eliminating extra join in JPA query by just using the FK column instead of the related entity's ID
我有一個實體關系,這樣:
STUDENT many-to-one STUDENT_COURSE one-to-many COURSE
基本上,學生和他們的課程之間存在many-to-many
關系。 這種關系由STUDENT_COURSE
表表示。
假設我為STUDENT
、 STUDENT_COURSE
和COURSE
設置了實體,使得:
@Entity
@Table(name = "STUDENT")
public course Student {
@Id
@Column(name = "ID", nullable = false)
private Long id;
@OneToMany(mappedBy = "student")
private Set<StudentCourse> studentCoursees;
// ... other fields and getters and setters
}
@Entity
@Table(name = "COURSE")
public course Course {
@Id
@Column(name = "ID", nullable = false)
private Long id;
@OneToMany(mappedBy = "course")
private Set<StudentCourse> studentCourses;
// ... other fields and getters and setters
}
@Entity
@Table(name = "STUDENT_COURSE")
public course StudentCourse {
@Id
@Column(name = "ID", nullable = false)
private Long id;
@ManyToOne
@JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID")
@NotNull
private Student student;
@ManyToOne
@JoinColumn(name = "COURSE_ID", referencedColumnName = "ID")
@NotNull
private Course course;
// ... other fields and getters and setters
}
然后我有一個復雜的標准查詢,我正在為搜索目的而創建,希望所有學生都參加特定課程。 我有要添加到限制中的courseId
。 在 SQL 中,我會做這樣的事情:
select *
from STUDENT, STUDENT_COURSE
where STUDENT.ID = STUDENT_COURSE.STUDENT_ID
and STUDENT_COURSE.COURSE_ID = <courseId>
請注意,我只加入STUDENT
和STUDENT_COURSE
。 使用上述設置的標准和實體,似乎我被迫加入STUDENT
、 STUDENT_COURSE
和COURSE
因為我在STUDENT_COURSE
上沒有 courseId 字段:
Join<Person, PersonCourse> personCourse = root.join("personCourses");
Join<PersonCourse, Course> course = personCourse.join("course");
Predicate onlySpecificCourse = builder.equal(course.get("id"), courseId);
這只是一些地方我都必須同時@ManyToOne
從StudentCourse到的課程領域和courseId
上StudentCourse場? 如果我將 courseId 字段聲明為:
@Column(name = "USER_ID", insertable = false, updatable = false)
private String userId;
然后加入變成:
Join<Person, PersonCourse> personCourse = root.join("personCourses");
Predicate onlySpecificCourse = builder.equal(personCourse.get("courseId"), courseId);
如果我這樣做,有什么我應該注意的問題嗎? 特別是,在PersonCourse
實體上同時使用courseId
和course
設置器似乎很奇怪。
我正在更新我的答案以為您提供解決方案,即使我不喜歡它。 :-)
但首先,聽起來您希望以 OOP 方式執行此操作,但您不想將持久化數據視為對象樹,因為 Person、PersonCourse 和 Course 都是同一對象樹的一部分,但是對於某些特殊情況,您可能會忘記這個事實。 您只能將 ORM 推到某個點,之后您將不得不退回到本機 SQL。
但是,我將在這里提供一個您可能不喜歡的 ORM 解決方案,所以在這里:
向 PersonCourse 實體添加一個新屬性並將其映射到連接表中的 COURSE_ID 列。 但是您必須確保在插入和更新中不使用新屬性。
@Column(name = "COURSE_ID", insertable = false, updatable = false)
private Long courseId;
現在您可以從等式中刪除 Course Root 並使用您在上面顯示的 Predicate。
如果 STUDENT_CLASS 表除了 STUDENT 和 CLASS 關系的 ID 之外沒有其他列,那么只需在 Student 和 Class 實體之間使用@ManyToMany ,而不是@ManyToOne ,並且不需要第三個實體; Hibernate 會為你處理它。
如果連接表確實有其他列,例如GRADE或RATING列,則使用如下所述的解決方案: 使用額外列映射多對多關聯表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.