Projections

Use Projections when the required result is a subset of an entity, that is when the required result is just a small part of the entity. You can define an interface or a POJO class with a subset of the properties found in the entity class. Then you use these interfaces or POJO classes as the parametrized type result of the custom repository methods.

Examples

The following examples are shown in the context of Student entity class. See Example: Accessing Oracle NoSQL Database Using Spring Data Framework to get the details on creating the Student entity class and the StudentRepository interface.
  1. Define an interface StudentView and a POJO class StudentProjection.
    public interface StudentView {
       String getLastName();
    }
    public class StudentProjection {
       private String firstName;
       private String lastName;
       public StudentProjection(String firstName, String lastName) {
          this.firstName = firstName;
          this.lastName = lastName;
       }
       public String getFirstName() {
          return firstName;
       }
       public void setFirstName(String firstName) {
          this.firstName = firstName;
       }
       public String getLastName() {
          return lastName;
      }
      public void setLastName(String lastName) {
         this.lastName = lastName;
      }
    }
  2. The new types (StudentView and StudentProjection) can be used as the result of the custom find methods in the StudentRepository class.
    import java.util.Date;
    import com.oracle.nosql.spring.data.repository.NosqlRepository;
    public interface StudentRepository
    extends NosqlRepository<Student, Long>
    {
       Iterable<Student> findByLastName(String lastname);
       Iterable<Student> findByCreatedAtBetween(Date start, Date end);
       Iterable<StudentView> findAllByLastName(String lastName);
       Iterable<StudentProjection> getAllByLastName(String lastName);
    }

    Since these results contain a subset of the row, if the Id property is not included the returned set could contain duplicates. If these duplicates are not required then you can use the Distinct keyword to eliminate them.

    Example:
    List<StudentView>findAllDistinctByLastName(String lastName);
    List<StudentProjection> getAllDistinctByLastName(String lastName);
    These methods will generate the following queries:
    declare $p_lastName String;
    select distinct {'lastName': t.kv_json_.lastName} as kv_json_ from Student \
                                  as t where t.kv_json_.lastName = $p_lastName
    declare $p_lastName String;
    select distinct {'firstName': t.kv_json_.firstName, 'lastName': t.kv_json_.lastName} as kv_json_ \
    from Student as t where t.kv_json_.lastName = $p_lastName

    Note:

    Only interface and class based projections that contain a subset of entity properties are supported by NoSQL SDK for Spring Data. Projections using @Value annotations are not supported. Dynamic projections, when return type is parametrized, are also not supported.
  3. Modify the run method and invoke the custom methods (defined with Projection interface and POJO Class).
    // Using projection interface
    System.out.println("\n With projection findAllByLastName: Smith");
    repo.findAllByLastName("Smith")
    .forEach(c -> System.out.println("StudentView :" + c));
    // using projection POJO class here
    System.out.println("\n With projection getAllByLastName: Smith");
    repo.getAllByLastName("Smith")
    .forEach(c -> System.out.println("StudentProjection.firstName :" + c.getFirstName()
                                + " StudentProjection.lastName :" + c.getLastName() ));

    Note:

    See Example: Accessing Oracle NoSQL Database Using Spring Data Framework to get more details on the AppConfig class to provide the connection details of the database and the App class that implements the run method and has the main method.
  4. Run the program from the runner class. You will get the following output.
    With projection findAllByLastName: Smith
    StudentView :Student{id=0, firstName='null', lastName='Smith', createdAt='null'}
    With projection getAllByLastName: Smith
    StudentProjection.firstName :John
    StudentProjection.lastName :Smith