When to use EntityManager.find() vs EntityManager.getReference() with JPA

I usually use getReference method when i do not need to access database state (I mean getter method). Just to change state (I mean setter method). As you should know, getReference returns a proxy object which uses a powerful feature called automatic dirty checking. Suppose the following

public class Person {

    private String name;
    private Integer age;

}


public class PersonServiceImpl implements PersonService {

    public void changeAge(Integer personId, Integer newAge) {
        Person person = em.getReference(Person.class, personId);

        // person is a proxy
        person.setAge(newAge);
    }

}

If i call find method, JPA provider, behind the scenes, will call

SELECT NAME, AGE FROM PERSON WHERE PERSON_ID = ?

UPDATE PERSON SET AGE = ? WHERE PERSON_ID = ?

If i call getReference method, JPA provider, behind the scenes, will call

UPDATE PERSON SET AGE = ? WHERE PERSON_ID = ?

And you know why ???

When you call getReference, you will get a proxy object. Something like this one (JPA provider takes care of implementing this proxy)

public class PersonProxy {

    // JPA provider sets up this field when you call getReference
    private Integer personId;

    private String query = "UPDATE PERSON SET ";

    private boolean stateChanged = false;

    public void setAge(Integer newAge) {
        stateChanged = true;

        query += query + "AGE = " + newAge;
    }

}

So before transaction commit, JPA provider will see stateChanged flag in order to update OR NOT person entity. If no rows is updated after update statement, JPA provider will throw EntityNotFoundException according to JPA specification.

regards,

Leave a Comment