[英]Designing hierarchy of parent child relationships with spring data jpa
我正在嘗試建立待辦事項日志管理員。 我正在將java spring-boot與基於hibernate構建的data-jpa一起使用。 我希望用戶擁有該用戶從事的多個項目 。 然后,每個項目都有幾個與之相關的任務 ,並且用戶通過完成簡短的原子工作單元( 日志條目 )來跟蹤每個任務花費了多少時間。
到目前為止,我最終構建了該系統的最幼稚的實現。 它看起來像是一對多層次結構中的幾個級別:用戶->項目->任務->條目。 當前的數據庫實現基於這樣的模式
實體類的代碼(為簡潔起見,省略了getters setters構造函數和一些注釋):
@MappedSuperclass
public abstract class AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
}
@Entity
public class User extends AbstractEntity {
@Column
private String name;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Project> projects;
}
@Entity
public class Project extends AbstractEntity {
@Column
private String name;
@OneToMany(mappedBy = "project", fetch = FetchType.LAZY)
private List<Task> tasks;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}
@Entity
public class Task extends AbstractEntity {
@Column
private String name;
@OneToMany(mappedBy = "task", fetch = FetchType.LAZY)
private List<Entry> entries;
@ManyToOne
@JoinColumn(name = "project_id")
private Project project;
}
@Entity
public class Entry extends AbstractEntity {
@Column
private Integer duration;
@Column
private LocalDateTime finish;
@ManyToOne
@JoinColumn(name = "task_id")
private Task task;
}
我希望能夠為用戶提供在用戶指定的時間范圍內查看所有日志條目的功能 。 我像這樣添加了jpa存儲庫:
public interface EntryRepository extends JpaRepository<Entry, Integer> {
@Query("SELECT e FROM Entry e WHERE (e.task.project.user.id=:user_id) AND " +
"(e.finish BETWEEN :from AND :to)")
List<Entry> getAllForUserInDateRange(@Param("from") LocalDateTime from,
@Param("to") LocalDateTime to,
@Param("user_id") int userId);
}
1)說此查詢效率低下是否正確? 我當時認為從數據庫執行這樣的獲取效率不高,因為查詢無法利用索引。 由於Entry表中沒有外鍵user_id,因此正在查找每一行,並遵循鏈入口->任務->項目->用戶。 我以線性復雜度而不是對數結尾。
2)解決該問題的更好方法是什么? 將外鍵存儲到用戶表中可以嗎? 如果我想從數據庫中獲取特定項目或任務的條目,那么我也必須向這些關系添加外鍵。 這可以嗎?
您應該檢查正在執行的真實SQL。 將org.hibernate.SQL
日志級別設置為DEBUG
,您將看到以下語句。
我認為對於您的查詢,您實際上將在四個表之間獲得三個內部聯接。 您說查詢無法利用索引。 絕對可以。 創建以下索引:
USER (ID)
PROJECT (USED_ID, ID)
TASK (PROJECT_ID, ID)
ENTRY(TASK_ID, ID)
請參閱使用索引,Luke中的 接觸索引 。
使用這些索引,您在四個表之間的聯接可能會使用索引。 我不會為此着火,但是應該可以。 檢查查詢計划。
你是正確的,鏈ENTRY
- > TASK
- > PROJECT
- > USER
將接踵而至,但它應該是相當faset與indixes
您的數據庫架構已非常規范化,這導致在四個表之間進行三個聯接。 您可以通過將user_id
引入ENTRY
來對此模式進行非規范化。 這可能會提高查詢性能,但老實說,我懷疑這會帶來很多好處。 在實際切換到此解決方案之前,您可能需要運行實際基准測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.