9

Lets consider these entities

@Entity
public class Room{

  @Id
  private Integer id;

  private String number;

  private String floor;

  @ManyToOne
  private RoomType roomType;

  // Setters & Getters  
}

@Entity
public class RoomType{

  @Id
  private Integer id;

  private String name;

  private String description;

  private Boolean enabled;

  // Setters & Getters  
}

And also this interface for projection alongside repository class

public interface RoomList{

    public Number getId();

    public String getNumber();

    public RoomType getRoomType();

    interface RoomType {
        String getName();
    }   

}

@Repository
public interface RoomRepository extends JpaRepository<Room,Integer>{

    public Collection<RoomList> findAllProjectedBy();

}

Now if I look at generated SQL

select
    room0_.id as col_0_0_,
    room0_.number as col_1_0_,
    roomtype1_.id as id1_3_,
    roomtype1_.description as descript2_3_,
    roomtype1_.enabled as isActive3_3_,
    roomtype1_.name as name5_3_ 
from
    Room room0_ 
inner join
    roomType roomtype1_ 
        on room0_.roomType_id=roomtype1_.id

The generated query should be something like this

select
    room0_.id as col_0_0_,
    room0_.number as col_1_0_,
    roomtype1_.name as name5_3_ 
from
    Room room0_ 
inner join
    roomType roomtype1_ 
        on room0_.roomType_id=roomtype1_.id

Can someone explain this behaviour or either this is a bug ? also what other options do we have achieve this kind of result. I already tried JPA entitygraph but graph type fetch is not yet fully supported in hibernate, i don't want to use constructor jpql query either. Thanks !

belnxkkk
  • 375
  • 1
  • 3
  • 11
  • Can you share the definition of `findAllProjectedBy` ? When you haven't described when the Query is generated what operation you performed. – JB's Nov 07 '17 at 13:56
  • `findAllProjectedBy()` works exactly like `findAll()` except I can only return `List` in `findAll()` but i can return `List` in `findAllProjectedBy()` or whatever i want. – belnxkkk Nov 07 '17 at 14:00
  • You have `RoomType` as an `interface` and as well as `class`, have you considered changing it. – JB's Nov 07 '17 at 14:04
  • I have `RoomType` as an class but not as an interface. Interface name is `RoomList` and configuration is as per spring data jpa reference documentation [link](https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections). [edit] `RoomType` inner interface is required for nested projections. – belnxkkk Nov 07 '17 at 14:07
  • 1
    `RoomType` inner interface is required by spring data jpa for nested projections also all configurations are correct. – belnxkkk Nov 07 '17 at 14:11
  • Consider changing their names like `RoomTypeSummary` or something like that. – JB's Nov 07 '17 at 14:11
  • Changing interface name to `RoomTypeSummary` gives runtime error as there is no field specified as `RoomTypeSummary` in `Room` entity. – belnxkkk Nov 07 '17 at 14:14
  • [Documentation](https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections) gives example of nested class between `Person` and `Address`, have you considered making the `RoomType` nested class of `Room` – JB's Nov 07 '17 at 14:21
  • This also have another issue. it always use inner join when query projection no matter what `(@JoinColumn(nullable=true) )` nullable is. – evolever Aug 23 '18 at 18:00

1 Answers1

8

If understand correctly the concern is that more attributes/columns get selected than necessary to fill the projections.

As I just described in issue DATAJPA-1218 this is just how projections work in Spring Data currently. The attributes of referenced entities do not get limited to those used in the projection.

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348