Consider following entities:
UserEntity:
@Entity(name = "user")
public class UserEntity {
    @Id
    @Column(name = "id", columnDefinition = "serial")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "name")
    private String name;
    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
    private List<RoleEntity> roles = new ArrayList<>();
}
RoleEntity:
@Entity(name = "role")
@NamedEntityGraph(
        name = "role.entity_graph",
        attributeNodes = {
                @NamedAttributeNode(value = "permissions")
        })
public class RoleEntity {
    @Id
    @Column(name = "id", columnDefinition = "serial")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "name")
    private String name;
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
    private List<PermissionEntity> permissions = new ArrayList<>();
}
PermissionEntity:
@Entity(name = "permission")
public class PermissionEntity {
    @Id
    @Column(name = "id", columnDefinition = "serial")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "name")
    private String name;
}
roles of the UserEntity should be fetched lazy. Problem is when the roles are used (getter is called), hibernate fetches them with a query for each role and a query for each permission of each role, resulting in the n+1 issue.
Thus my question is: How can I lazy fetch the user roles with one query? Can I somehow utilize RoleEntity's EntityGraph?
Note: I already tried using @Fetch:
@Fetch(FetchMode.JOIN)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
private List<PermissionEntity> permissions = new ArrayList<>();
This did not work. However together with @BatchSize it works as excpeted.
@Fetch(FetchMode.JOIN)
@BatchSize(size = 1000)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
private List<PermissionEntity> permissions = new ArrayList<>();
I'm not happy with this solution though. Why do I need to add @BatchSize?