Previous Next JavaScript must be enabled to correctly display this content

## Projections

Learn to use Projections to customize a part of the entity class.

Use Projections when the required result is a subset of an entity, that is when the required result is 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.

Example 2-6 Using Projections

The following example defines projections in the context of `Student` entity class. See 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. You can use the new types (`StudentView` and `StudentProjection`) 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 must contain duplicates. If these duplicates are not required then you can use the `Distinct` keyword to eliminate them as follows:

       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 Oracle NoSQL Database 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 call 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 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