Search code examples
javajpaspring-datalazy-loadingprojection

Projections do not load ManyToOne relations lazily


I have an entity representing a MySQL table:

@Entity
@Table(name = "group_")
@Getter
@Setter
@SuppressWarnings("serial")
public class GroupEntity
        implements Serializable {

    @Id
    @GeneratedValue(generator = "uuid2")
    @Column(name = "group_id")
    private UUID groupId;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "owner_account_id")
    @NotNull
    private AccountEntity ownerAccount;

    @Column(name = "value")
    @NotBlank
    private String value;

}

And a projection:

public interface GroupBaseProjection {

    UUID getGroupId();

    AccountEntity getOwnerAccount();

}

This is my repository:

public interface GroupsRepository extends JpaRepository<GroupEntity, UUID> {

    GroupBaseProjection findBaseByGroupId(UUID groupId);

}

When I retrieve the entity, the ownerAccount is loaded lazily (the Hibernate MySQL query only selects its ID) but when I retrieve the projection, it is loaded eagerly (the Hibernate MySQL query does an inner join with all the AccountEntity columns). So there is no way I can retrieve only some columns of the GroupEntity (I have to retrieve all of them using the entity, or some of them plus all the columns of the AccountEntity using the projection).

Is there a way I can get the projection to load the @ManyToOne relation lazily? I've tried annotating the getOwnerAccount() method of projection with @ManyToOne(fetch = FetchType.LAZY, optional = false) and @LazyToOne(LazyToOneOption.PROXY) but it did not work.


Solution

  • So there is no way I can retrieve only some columns of the GroupEntity

    Sure there is, just use a nested projection:

    public interface AccountProjection {
    
        Long getId();
    
        String getName();
    
       ... // other columns
    
    } 
    
    public interface GroupBaseProjection {
    
        UUID getGroupId();
    
        AccountProjection getOwnerAccount();
    
    }
    
    

    Is there a way I can get the projection to load the @ManyToOne relation lazily?

    I wouldn't think so, since projections are not entities, and so they are not managed by JPA.

    EDIT It would seem nested projections select all the entity properties anyway (see comments). As a workaround, if you're only interested in the id, you could try mapping the join column once again as a simple property:

    @Column(name = "owner_account_id", insertable = false, updatable = false)
    private Long ownerAccountId;
    

    this way, you'll be able to make it part of the projection.