spring-data-jpa
spring-data-jpa copied to clipboard
Closed Projection does not work with @EntityGraph [DATAJPA-1501]
asfernandes opened DATAJPA-1501 and commented
I have entities that map others entities using @ManyToOne(fetch = FetchType.LAZY).
// Endereco.java
@Entity
@Table(name = "enderecos")
public class Endereco
{
private Integer codigo;
private Cidade cidade;
@Id
public Integer getCodigo()
{
return super.getCodigo();
}
public void setCodigo(Integer codigo)
{
this.codigo = codigo;
}
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "cid_codigo")
public Cidade getCidade()
{
return cidade;
}
public void setCidade(Cidade cidade)
{
this.cidade = cidade;
}
}
// Cidade.java
@Entity
@Table(name = "cidades")
public class Cidade
{
private Integer codigo;
private String nome;
@Id
public Integer getCodigo()
{
return super.getCodigo();
}
public void setCodigo(Integer codigo)
{
this.codigo = codigo;
}
public String getNome()
{
return nome;
}
public void setNome(String nome)
{
this.nome = nome;
}
}
Then I have created a repository interface with a method using @EntityGraph:
@EntityGraph(type = EntityGraphType.FETCH,
attributePaths = {
"cidade"
}
)
<T> List<T> findFetchCidade(Class<T> type);
And created projection interfaces:
public interface EnderecoProjection
{
Integer getCodigo();
CidadeProjection getCidade();
/*
@Value("#{target.codigo}")
Integer getSomething();
*/
}
public interface CidadeProjection
{
Integer getCodigo();
String getNome();
}
When I use findFetchCidade passing a EnderecoProjection, I have this error:
org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
Note that if I uncomment the @Value annotation, the projection becomes opened and then no error happens
Affects: 2.1.4 (Lovelace SR4)
Oliver Drotbohm commented
This looks like a wild mixture of entity graphs and projections, which we didn't quite anticipate before. What's the reason you need to mix those up? EnderecoProjection.getSomething() could just be a default method, couldn't it?
asfernandes commented
If the projection is used directly (no generics) in findFetchCidade, the same thing happens
asfernandes commented
Oliver Drotbohm I don't need the getSomething. It's used just to make the thing work. My real case is some nesting of projections (Endereco -> Cidade -> Estado -> Pais), that I need some fields of each, and I want to have LAZY in the entities
asfernandes commented
Oliver Drotbohm you say the problem is the mixture of entity graphs and projections, but for me the problem seems to be about nested projections not creating a JPQL selecting the fetched entities. At least that seems to be what the error says.
It's weird because nested projections is documented as something supported
Just found this after logging my issue (https://github.com/spring-projects/spring-data-jpa/issues/2709)
This repo demonstrates that entity graph is ignored in Spring-Data when it is used in combination with closed-projection:
https://github.com/Eng-Fouad/spring-closed-projection-entity-graph
As a workaround:
@EntityGraph(value = "SomeEntityGraph")
EntityClass queryById(int id);
EntityClass entity = entityRepo.queryById(1);
EntityProjection entityProjection = new CollectionAwareProjectionFactory().createProjection(EntityProjection.class, entity);
However, the generated query will include all columns in SELECT clause, as the return type is EntityClass not EntityProjection.
Any updates regarding this issue? @odrotbohm @mp911de @schauder @gregturn @christophstrobl
The actual question is: What should happen if a closed projection and an @EntityGraph are defined? Do we ignore the entity graph or do we ignore the reduction of columns as per the projection definition?