How to use EntityGraph

129 Views Asked by At

I am working to resolve N+1 (actually more like 10N+1) issues with reports being generated through one of our apps, and i am trying to limit what data is loaded by hibernate (5.3.20.Final) and came across EntityGraph's. My understanding is that i should be able to specify exactly what data to load and what not to (by omission), something like this:

        EntityGraph<RegistrantEntity> registrantEntityGraph = entityManager.createEntityGraph(RegistrantEntity.class);
        registrantEntityGraph.addAttributeNodes(
                "id",
                "createdTimestamp",
                "firstName",
                "lastName",
                "email");


        return entityManager.createNamedQuery("RegistrantEntity.findByRegistrationIds", RegistrantEntity.class)
                .setHint("javax.persistence.loadgraph", registrantEntityGraph)
                .setParameter("registrationIds", registrationIds)
                .getResultList();

I assume i must be doing something wrong since when the above code runs hibernate is fetching more than is specified in the graph and related records:

10:06:22,018 INFO  [stdout] (default task-1) Hibernate: select *numerous columns including some that are not specified in the graph* from registrants registrant0_ where registrant0_.registration_id in (? , ? ...)

Then it also loads related records:

10:06:40,738 INFO  [stdout] (default task-1) Hibernate: select *a bunch of columns* from docusign docusignen0_ where docusignen0_.registrant_id=?

RegistrantEntity info:

public class RegistrantEntity implements java.io.Serializable
{
    @Id
    @Type(type = "pg-uuid")
    private UUID id;

    private String firstName;
    private String lastName;
    private String email;

    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinColumn(name = "PERSON_ID")
    private PersonEntity personEntity;

    @OneToOne(mappedBy = "registrantEntity", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "docusign_id")
    private DocusignEntity docusignEntity;
…

DocusignEntity info:

public class DocusignEntity implements Serializable
{
    @Id
    @Type(type = "pg-uuid")
    private UUID id;

    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime createdTimestamp;

    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime transactionTimestamp;

    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime lastUpdatedTimestamp;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "registrant_id")
    private RegistrantEntity registrantEntity;

    @Type(type = "pg-uuid")
    private UUID envelopeId;

    private String status;

Wondering what might be going on here?

EDIT: I'll acknowledge that i'm not sure if loading only specific columns of an entity should happen or not (i.e. if only some variables in my RegistrantEntity should be loaded), but it most assuredly shouldn't load the docusign info, right?

EDIT 2: Interesting thing i noticed while doing some debugging today, if i load load DocusignEntity's or RegistrantEntity's it loads the other that is associated, regardless of if EntityGraph is used or not. Weird, could be the underlying cause, any thoughts on this?

0

There are 0 best solutions below