Description
Even if an interface projection (DTO) is used as the return type of the findAll() method of a repository, the method returns the entity associated with the repository, instead of the DTO.
I create an entity (reduced for compactness):
@Entity
@Table(name = "arpsi")
public class Arpsi {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String nombre;
private String codigo;
@JsonRawValue
private String dph;
// getters and setters not shown
}
I create a DTO with fewer fields:
public interface ArpsiDTO {
public Long getId();
public String getNombre();
}
I create a repository:
public interface ArpsiRepository extends Repository<Arpsi, Long> {
Iterable<ArpsiDTO> findById();
Iterable<ArpsiDTO> findAll();
...
}
I use a service that uses the repository to retrieve the data. I use ArpsiDTO as the return type in every step, but the service gets the Entity instead of the DTO (with errors due to lazy initialization of a collection).
I tested it with several repositories, and only methods that include any condition (findByX or similar) return the DTO.
Converting the ArpsiDTO to a class, and using a constructor based projection with a custom query for the findAll() method works as expected (returns the DTO):
@Query("SELECT new com.equixlab.api.model.augas.arpsi.ArpsiDTO(a.id, a.nombre, a.codigo) FROM Arpsi a")
Iterable<ArpsiDTO> findAll();
It also works if we create a method with an always true condition, such as:
Iterable<ArpsiDTO> findAllByIdNotNull();
I suppose this happens with all the methods that exist in the CrudRepository interface and expose in a Repository interface (inspecting the CrudRepository interface, the methods use <T>
or <S extends T>
, so a DTO cannot be used/returned).
Is this by design? I could not find anything in the docs.