2

I have an entity as

    @Getter
    @Setter
    @Entity
    @Table(name = "feature")
    @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
    public class Feature {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;

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

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

        @OneToMany(mappedBy = "featureId", fetch = FetchType.LAZY)
        private transient Collection<FeatureComponent> components;
}

While in its Repository(Dao) file, I have

public interface FeatureDao extends JpaRepository<Feature, Integer> {

    @Query("SELECT e FROM Feature e")
    public List<Feature> getAll();

    @Query("SELECT e FROM Feature e LEFT JOIN e.components fc WHERE e.id= :id")
    public Feature getWithDetail(@Param("id") Integer id);
}

When I'm calling featureDao.getAll(); it returns all features but including components list filled and because of that, my response it being too large to load on client-side.

I'm unable to understand why it is happening when I'm using Lazy fetch mode and didn't mentioned joining with components in my getAll method.

Please help to resolve that issue, Thanks in advance.

  • Why not use `findAll()` of `JpaRepository`? – Mansoor Sep 27 '21 at 16:29
  • @Mansoor, Actually I have to add a where clause with a sub query... to avoid complexity in question, I skipped that part... – M.Haris Qayyum Sep 27 '21 at 16:59
  • My guess would be https://stackoverflow.com/a/21749892/1225328, i.e. Jackson triggering the unwanted queries to `FeatureComponent` when seralising your `List` since it finds a getter for `components`. – sp00m Sep 27 '21 at 17:18
  • But I don't want to avoid that 'components' because I need them for other purposes (that you can check in my other query i.e. getWithDetail)... I Know, We can easily ignore entity fields by @JsonIgnore annotation... – M.Haris Qayyum Sep 27 '21 at 17:54

3 Answers3

1

Just like @spOOm already mentioned I also suspect this is the side effect of Jackson Feature entity serialization into JSON triggering the load of all the components.

That is why using DTOs instead of plain Entities is usually advisable when returning data via a Controller. With DTOs, you clearly define whatever you want to include in the response to the caller. You can even reorganize your model so that it fits better the needs of the clients. You decouple your inner model and the model your API consumers know, making it possible to rework your inner model and still keep the same public model. You could have the following DTO.

public class FeatureSimpleDto {
    private Integer id;
    private String name;
    private String description;
}

Then, in your Controller or Service (here you can find different opinions) you would basically convert your Feature entity into a FeatureSimpleDto that would be returned by your Controller. Here you can use mapping libraries such as MapStruct or you can do it on your own (I usually tend to prefer doing it on my own, one less dependency to rely on).

João Dias
  • 16,277
  • 6
  • 33
  • 45
0

Using Lombok may be a problem, depending on the relationship between tables, try to create getters manually in entity classes.

serob
  • 34
  • 1
  • 4
0

Thanks to everyone for providing workarounds... But every work item requires lots of changes which were not possible for me...

Luckily I found a solution that is working fine for me... Better to post here...

Step-1: Add dependency in pom.xml file

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-hibernate5</artifactId>
</dependency>

Step-2: Add a 'Bean' for Hibernate Module

We can add bean in any file having @Configuration annotation... Even, we can add in Springboot main application file(where we have main method).

@Bean
public Module datatypeHibernateModule() {
    return new Hibernate5Module();
}

That's it, Happy Coding...