2017-08-31 53 views
4

我有一個具有onetomany關係(ContactInfo)的JPA實體(Person)。OneToMany的Spring Data Projection返回的結果太多

@Entity 
public class Person { 
    @Id 
    @GeneratedValue 
    private Integer id; 
    private String name; 
    private String lastname; 
    private String sshKey; 
    @OneToMany(mappedBy = "personId") 
    private List<ContactInfo> contactInfoList; 
} 

@Entity 
public class ContactInfo { 
    @Id 
    @GeneratedValue 
    private Integer id; 
    private Integer personId; 
    private String description; 
} 

我定義包括該一對多關係如所描述here投影接口。

public interface PersonProjection { 
    Integer getId(); 
    String getName(); 
    String getLastname(); 
    List<ContactInfo> getContactInfoList(); 
} 

public interface PersonRepository extends JpaRepository<Person,Integer> { 
    List<PersonProjection> findAllProjectedBy(); 
} 

當我檢索與findAllProjectedBy結果中包含太多的行中的數據。它看起來像返回的數據是一個連接查詢的相似結果:

select p.id, p.name, p.lastname, ci.id, ci.person_id, ci.description 
from person p 
join contact_info ci on ci.person_id = p.id 

例如,對於該數據集:

insert into person (id,name,lastname,ssh_key) values (1,'John','Wayne','SSH:KEY'); 

insert into contact_info (id, person_id, description) values (1,1,'+1 123 123 123'), (2,1,'[email protected]'); 

findAllProjectedBy方法返回2個對象(不正確地)與標準findAll返回1個對象(正確)。

全部項目here

我做了一些調試,似乎問題出在JPA查詢。 的的findAll方法使用此查詢:

select generatedAlias0 from Person as generatedAlias0 

的findAllProjectedBy使用此查詢:

select contactInfoList, generatedAlias0.id, generatedAlias0.name, generatedAlias0.lastname from Person as generatedAlias0 
left join generatedAlias0.contactInfoList as contactInfoList 

有誰知道如何解決這個無效的行爲?

+0

這是正常行爲。你真的想用投影來實現什麼?也許你只需要加載一個包含'ContactInfo'的人員列表? – Cepr0

+0

'正常行爲' - 在任何地方記錄?我正在實現的通用用例是一個帶查看參數的api。視圖可以是完整的(findAll)或有限的(findAllProjectedBy)。我希望能夠限制從數據庫檢索到的數據。上面的例子非常簡單。 – lbd01

+0

看起來像一個錯誤/缺少功能給我。你能開一個問題嗎? https://jira.spring.io/browse/DATAJPA/?selectedTab=com.atlassian.jira.jira-projects-plugin:summary-panel –

回答

4

要快速解決這個問題說明如下: https://jira.spring.io/browse/DATAJPA-1173

你需要描述單個突出的一個具有@Value註釋屬性。對於上面發佈的示例,您最終會得到:

import java.util.List; 
import org.springframework.beans.factory.annotation.Value; 

public interface PersonProjection { 
    @Value("#{target.id}") 
    Integer getId(); 
    String getName(); 
    String getLastname(); 
    List<ContactInfo> getContactInfoList(); 
} 
+0

這個註解使得這個投影是'open'而不是'closed'。他們通過假設投影默認爲「開放」來解決這個bug,以防其中一個方法返回集合或地圖。 – Sam

+0

當你使用Dto對象的界面時它不工作!我得到了:org.hibernate.hql.internal.ast.QuerySyntaxException:期待OPEN,發現','靠近第1行,第157列 – pustypawel

+1

@Sam好點。這樣做的結果是,當在投影中返回實體子集列時,hibernate會選擇所有列。 – lbd01