Lazy-loaded collections are accessible even when not included in fetch plan

When loading an entity with DataManager.load(...).fetchPlan("minimal-plan").one() inside a screen controller, lazy associations (e.g., @OneToMany, @ManyToMany) that are not included in the fetch plan are still accessible.

Steps to Reproduce:

  1. Define an entity ProjectInfo with:
    • @OneToMany List<Video> videos
    • @ManyToMany List<Image> images
    @JoinTable(name = "TP_PROJECT_INFO_IMAGE_LINK",
            joinColumns = @JoinColumn(name = "PROJECT_INFO_ID", referencedColumnName = "ID"),
            inverseJoinColumns = @JoinColumn(name = "IMAGE_ID", referencedColumnName = "ID"))
    @ManyToMany(cascade = {CascadeType.PERSIST}, fetch=FetchType.LAZY)
    private List<Image> images;

    @OneToMany(mappedBy = "projectInfo", cascade = {CascadeType.PERSIST}, fetch = FetchType.LAZY)
    private List<Video> videos;
  1. Create a fetch plan that includes only the name property.
<fetchPlans xmlns="http://jmix.io/schema/core/fetch-plans">
  <fetchPlan entity="tp_ProjectInfo" name="projectInfo-fetch-plan" overwrite="true" extends="_instance_name">
      <property name="name"/>
  </fetchPlan>
</fetchPlans>
  1. Load it in a screen:
    ProjectInfo result = dataManager.load(ProjectInfo.class)
        .id(id)
        .fetchPlan("projectInfo-fetch-plan")
        .one();
    
    

Accessing:

        ProjectInfo result1 = dataManager.load(ProjectInfo.class)
                .id(result.getId())
                .fetchPlan("projectInfo-fetch-plan")
                .one();
        System.out.println("Videos loaded? " + entityStates.isLoaded(result1, "videos")); // false
        System.out.println("Images loaded? " + entityStates.isLoaded(result1, "images")); // false

        System.out.println("Now accessing lazy collections...");
        System.out.println("Image count: " + result1.getImages().size()); // DB fetch
        System.out.println("Video count: " + result1.getVideos().size()); // DB fetch

        System.out.println("Videos loaded (after)? " + entityStates.isLoaded(result1, "videos")); // true
        System.out.println("Images loaded (after)? " + entityStates.isLoaded(result1, "images")); // true

Output:

Videos loaded? false
Images loaded? false
Now accessing lazy collections...
Image count: 1
Video count: 1
Videos loaded (after)? true
Images loaded (after)? true

According to the fetch plan, data manager should not load the images and videos in the entity.

Thanks.

Hello @vimalkumar010 !

Fetch plan does not restrict lazy loading. It just says which attributes to load during single load operation.
Please, see more details in the documentation:

Fetch plans are fully compatible with lazy loading of related entities. It means that you can load some part of a graph with a fetch plan, and then load other related entities lazily by navigating references.

Regards,
Dmitry