I want to use projections to fetch only specific fields from my database with Spring Data JPA.
This is my (shortened) data model:
@Entity
@Table(name = "data")
@Data
public class DataEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String description;
@LazyCollection(LazyCollectionOption.FALSE)
@Fetch(value = FetchMode.SUBSELECT)
@OneToMany(mappedBy = "data", fetch = FetchType.LAZY)
@Builder.Default
private List<OwnerEntity> owners = new ArrayList<>();
}
@Entity
@Table(name = "owner")
@Data
public class OwnerEntity {
@EmbeddedId
public OwnerId id = new OwnerId();
@Fetch(value = FetchMode.JOIN)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="userId", insertable = false, updatable = false)
private UserEntity user;
@ManyToOne
@JoinColumn(name="dataId", insertable = false, updatable = false)
private InterfaceEntity iface;
}
@Embeddable
@Data
public class OwnerId implements Serializable {
private Integer dataId;
private String userId;
}
@Entity
@Table(name = "users")
@Data
public class UserEntity {
@Id
private String id;
private String name;
private String mail;
}
This is my projection:
public interface DataProjection {
String getName();
String getDescription();
List<UserEntity> getOwners();
}
Finally, this is my DAO:
public interface DataDao extends CrudRepository<DataEntity, Integer> {
@Query("select d.name as name, " +
" d.description as description, " +
" o.user as owners " +
"from DataEntity d " +
"left join d.owners o " +
"order by d.name")
List<DataProjection> getData();
}
It generally works but it returns one row for each owner resulting in multiple same DataProjection
s with a list containing only one of the owners.
A similar problem was mentioned in this question but as mentioned in the solutions comments this would make it an open projection loading all columns. Is there a solution other than mapping the resulting rows programmatically?