2017-08-31 54 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