我需要幫助在JPA中生成查詢。比方說,我有這些表JPA:如何定義沒有N + 1問題的複雜計數
create table PERSON (
person_id number(3,0) not null primary key,
last_name varchar2(15) not null,
first_name varchar2(15) not null,
department varchar2(15) not null
);
create table PHONE (
phone_id number(3,0) not null primary key,
person_id number(3,0) not null,
phone_type varchar2(10) not null,
CONSTRAINT fk_person_id FOREIGN KEY (person_id)
REFERENCES person (person_id)
);
我想定義諸如查詢:定義如下
select p1.person_id, p1.last_name, p1.first_name,
(select count(1) from phone p2
where p2.person_id = p1.person_id) as phone_count
from person p1;
我的JPA類:
@Entity
@Table(name="PERSON")
@Transactional(readOnly=true)
public class Person {
@Id
@Column(name = "PERSON_ID")
private Integer personId;
@Column(name = "LAST_NAME")
private String lastName;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "DEPARTMENT")
private String department;
@OneToMany
@LazyCollection(LazyCollectionOption.FALSE)
@Fetch(FetchMode.SELECT) // or @Fetch(FetchMode.JOIN)
@JoinColumn(name = "PERSON_ID", referencedColumnName="PERSON_ID")
private Set<Phone> phones;
.... getters and setters...
}
@Entity
@Table(name="PHONE")
@Transactional(readOnly=true)
public class Person {
@Id
@Column(name = "PHONE_ID")
private Integer phoneId;
@Column(name = "PERSON_ID")
private Integer personId;
@Column(name = "PHONE_TYPE")
private String phoneType;
.... getters and setters ...
}
因爲我有動態where子句,即姓氏,名字,部門組合可以根據需要傳入。我有一個函數:
personRepository.findAll(spec, pageable);
,幫助我解決where子句,然後我通過getPhones.size拿到手機數量的動態()。它按預期工作。但是,它會產生N + 1問題。如果我有500多人,它會循環每個人的記錄並在電話桌上呼叫選擇查詢。我的問題是如何在這種情況下避免N + 1問題。
我想使用本機查詢以及我不知道如何使動態where子句工作(我真正的程序有超過15列過濾)。幫助表示讚賞。
通常對於普通的查詢,我會簡單地建議添加'來自Person p left join fetch p.phones'。雖然不熟悉'Specification'的使用。一個快速檢查似乎表明'Root'允許你定義'fetch',這又轉化爲一個聯合抓取,爲此你可以在構建規範時做些什麼 –
@Fetch(FetchMode.JOIN)將執行左連接取,我假設,但沒有。它仍然給了我N + 1個查詢。 –
我幾乎從不依賴實體中的渴望獲取定義,因爲1.它不總是工作,2.我無法控制。我寧願控制查詢中的取回行爲,而不是 –