Spring Data query methods usually return one or multiple instances of the aggregate root managed by the repository. However, it might sometimes be desirable to create projections based on certain attributes of those types. Spring Data allows modeling dedicated return types, to more selectively retrieve partial views of the managed aggregates.
Projection is just a way to retrieve certain fields from the database without retrieving all fields. This improves performance as it does not retrieve all fields.
There are 3 different types of projection: Scalar, DTO, Entity projection
Scalar Projection
Scalar projection allows you to select columns you need.
@Repository public interface BookRepository extends JpaRepository<User, Long> { @Query("SELECT u.name, u.email FROM Book b") List<Object[]> getNameAndEmail(); }
DTO Projection
DTO projection uses a constructor which Hibernate uses to populate data from the database.
@Repository public interface UserRepository extends CrudRepository<User, Long> { @Query("SELECT new com.kaveinga.user.dto.UserDetailDTO(u.firstName, u.lastName) FROM User user WHERE user.firstName = :firstName") List<UserDetailDTO> findByFirstName(String firstName); }
JPA DTO
As long as the DTO class has only one constructor and its parameter names match your entity class’s attribute names, Spring generates a query with the required constructor expression.
public interface UserRepository extends JpaRepository<User, Long> { UserDTO findByEmail(String email); }
public class UserDTO { private Long id; private String uid; private String name; private String email; private int age; private Address address; public UserDTO(Long id, String uid, String name, String email, int age, Address address) { super(); this.id = id; this.uid = uid; this.name = name; this.email = email; this.age = age; this.address = address; } // getters and setters }
JPA DTO as interface
Here is another way you can retrieve data from the database. Instead of having a DTO class you can use an interface. Your interface only defines getter methods for basic attributes.
public interface UserRepository extends JpaRepository<User, Long> { UserView findByUid(String uuid); }
public interface UserView { Long getId(); String getName(); String getEmail(); int getAge(); String getUid(); // nested object AddressView getAddress(); }