javahibernatehibernate-native-query

Hibernate query method requires all columns being returned in query?


I have written a native query for a repository method that groups by specific columns.

I can't group by id as that will break the grouping.

      @Query(nativeQuery = true, value = "SELECT description, model_year, take_rate, number " +
          "FROM foo f " +
          "INNER JOIN bar b " +
          "ON b.cycle_plan_code = b.cycle_plan_code " +
          "WHERE b.programme = :programme " +
          "AND b.build_event = :buildEvent " +
          "AND f.vehicle_line = :vehicleLine " +
          "GROUP BY description, take_rate, model_year, number")
  List<FooEntity> findAllFooByBar(@Param("vehicleLine") String vehicleLine, @Param("programme") String programme,
                                          @Param("buildEvent") String buildEvent);

My entity has an @Id column and some others

@Table(name = "foos")
public class FooEntity {

  @Id
  private Long id;

  @Column(name = "cycle_plan_code")
  private String cyclePlanCode;

  @Column(name = "model_year")
  private String year;

  @Column(name = "vehicle_line", nullable = true)
  private String vehicleLine;

  @Column(name = "number")
  private Integer number;

  @Column(name = "description")
  private String description;

  @Column(name = "take_rate")
  private double takeRate;

}

When accessing the repository method it throws a hibernate

o.h.engine.jdbc.spi.SqlExceptionHelper   : Column 'id' not found.

I tried to hack it by adding this to the select clause

SELECT 0 as id

This progresses, however it then complains the query doesn't return the other columns for the entity vehicle_line , model_year I had to add them all to the query to make it work.

I tried the nullable = true flag in the annotation but that didn't allow me to omit columns from the select clause.

How can I return entities with only some of the columns being returned that I am interested in?


Solution

  • Try using Projections: Declare an interface with the getters of the fields you want:

    public interface SubFooEntity{
    String getDescription();
    String getModelYear();
    Double getTakeRate();
    Integers getNumber(); 
    }
    

    Change repository method to below:

     @Query("SELECT description, modelYear, takeRate, number " +
          "FROM foo f " +
          "INNER JOIN bar b " +
          "ON b.cyclePlanCode = b.cyclePlanCode " +
          "WHERE b.programme = :programme " +
          "AND b.build_event = :buildEvent " +
          "AND f.vehicle_line = :vehicleLine " +
          "GROUP BY description, takeRate, modelYear, number")
    
    
    List<SubFooEntity> findAllFooByBar(@Param("vehicleLine") String vehicleLine, @Param("programme") String programme,
                                              @Param("buildEvent") String buildEvent);
    

    More on it here: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections