Spring Data Projection with OneToMany returns too many results

lbd01 :

I have a JPA entity (Person) with onetomany relation (ContactInfo).

@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;
}

I've defined a projection interface that includes this onetomany relation as described here.

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

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

When I retrieve the data with findAllProjectedBy the result contains too many rows. It looks like the returned data is the result of a join query similar to:

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

For example for this data set:

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]');

The findAllProjectedBy method returns 2 objects (incorrectly) and the standard findAll returns 1 object (correctly).

Full project is here

I've done some debugging and it seems that the problem is with the jpa query. The findAll method uses this query:

select generatedAlias0 from Person as generatedAlias0

The findAllProjectedBy uses this query:

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

Does anyone know how to fix this invalid behaviour?

lbd01 :

A quick fix for this problem is described here: https://jira.spring.io/browse/DATAJPA-1173

You need to describe one of the single projection attributes with a @Value annotation. For the example posted above you will end up with:

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();
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=477069&siteId=1