title: Why are interface projections much slower than constructor projections and entity projections in Spring Data JPA with Hibernate?
body: <p>I've been wondering which kind of projections should I use, so I did a little test, which covered 5 types of projections (based on docs: <a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections" rel="noreferrer">https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections</a>):</p>
  
  <p><strong>1. Entity projection</strong></p>
  
  <p>This is just a standard <code>findAll()</code> provided by Spring Data repository. Nothing fancy here.</p>
  
  <p>Service:</p>
  
  <pre><code>List&lt;SampleEntity&gt; projections = sampleRepository.findAll();
  </code></pre>
  
  <p>Entity:</p>
  
  <pre><code>@Entity
  @Table(name = "SAMPLE_ENTITIES")
  public class SampleEntity {
      @Id
      private Long id;
      private String name;
      private String city;
      private Integer age;
  }
  </code></pre>
  
  <p><strong>2. Constructor projection</strong></p>
  
  <p>Service:</p>
  
  <pre><code>List&lt;NameOnlyDTO&gt; projections = sampleRepository.findAllNameOnlyConstructorProjection();
  </code></pre>
  
  <p>Repository:</p>
  
  <pre><code>@Query("select new path.to.dto.NameOnlyDTO(e.name) from SampleEntity e")
  List&lt;NameOnlyDTO&gt; findAllNameOnlyConstructorProjection();
  </code></pre>
  
  <p>Data transfer object:</p>
  
  <pre><code>@NoArgsConstructor
  @AllArgsConstructor
  public class NameOnlyDTO {
      private String name;
  }
  </code></pre>
  
  <p><strong>3. Interface projection</strong></p>
  
  <p>Service:</p>
  
  <pre><code>List&lt;NameOnly&gt; projections = sampleRepository.findAllNameOnlyBy();
  </code></pre>
  
  <p>Repository:</p>
  
  <pre><code>List&lt;NameOnly&gt; findAllNameOnlyBy();
  </code></pre>
  
  <p>Interface:</p>
  
  <pre><code>public interface NameOnly {
      String getName();
  }
  </code></pre>
  
  <p><strong>4. Tuple projection</strong></p>
  
  <p>Service:</p>
  
  <pre><code>List&lt;Tuple&gt; projections = sampleRepository.findAllNameOnlyTupleProjection();
  </code></pre>
  
  <p>Repository:</p>
  
  <pre><code>@Query("select e.name as name from SampleEntity e")
  List&lt;Tuple&gt; findAllNameOnlyTupleProjection();
  </code></pre>
  
  <p><strong>5. Dynamic projection</strong></p>
  
  <p>Service:</p>
  
  <pre><code>List&lt;DynamicProjectionDTO&gt; projections = sampleRepository.findAllBy(DynamicProjectionDTO.class);
  </code></pre>
  
  <p>Repository:</p>
  
  <pre><code>&lt;T&gt; List&lt;T&gt; findAllBy(Class&lt;T&gt; type);
  </code></pre>
  
  <p>Data transfer object:</p>
  
  <pre><code>public class DynamicProjectionDTO {
  
      private String name;
  
      public DynamicProjectionDTO(String name) {
          this.name = name;
      }
  }
  </code></pre>
  
  <p><br>
  <strong>Some additional info:</strong></p>
  
  <p>The project was built using gradle spring boot plugin (version 2.0.4), which uses Spring 5.0.8 under the hood. Database: H2 in memory.</p>
  
  <p><strong>Results:</strong></p>
  
  <pre><code>Entity projections took 161.61 ms on average out of 100 iterations.
  Constructor projections took 24.84 ms on average out of 100 iterations.
  Interface projections took 252.26 ms on average out of 100 iterations.
  Tuple projections took 21.41 ms on average out of 100 iterations.
  Dynamic projections took 23.62 ms on average out of 100 iterations.
  -----------------------------------------------------------------------
  One iteration retrieved (from DB) and projected 100 000 objects.
  -----------------------------------------------------------------------
  </code></pre>
  
  <p><strong>Notes:</strong></p>
  
  <p>It is understandable that retrieving entities takes some time. Hibernate tracks these objects for changes, lazy loading and so on.</p>
  
  <p>Constructor projections are really fast and have no limitations on the DTO side, but require manual object creation in <code>@Query</code> annotation.</p>
  
  <p>Interface projections turned out to be really slow. See question.</p>
  
  <p>Tuple projections were the fastest, but are not the most convinient to play with. They need an alias in JPQL and the data has to be retrieved by calling <code>.get("name")</code> instead of <code>.getName()</code>.</p>
  
  <p>Dynamic projections look pretty cool and fast, but must have exactly one constructor. No more, no less. Otherwise Spring Data throws an exception, because it doesn't know which one to use (it takes constructor parameters to determine which data to retrieve from DB).</p>
  
  <p><strong>Question:</strong></p>
  
  <p>Why interface projections take longer than retrieving entities? Each interface projection returned is actually a proxy. Is it so expensive to create that proxy? If so, doesn't it defeat the main purpose of projections (since they are meant to be faster than entities)? Other projections look awesome tho. I would really love some insight on this. Thank you.</p>
  
  <p><strong>EDIT :</strong>
  Here is the test repository: <a href="https://github.com/aurora-software-ks/spring-boot-projections-test" rel="noreferrer">https://github.com/aurora-software-ks/spring-boot-projections-test</a> in case you want to run it yourself. It is very easy to set up. Readme contains everything you need to know.</p>