Search code examples
javajpaeclipselinksetter

Multiple calls to entities "setter" methods by EclipseLink


Can somebody explain this behaviour?

Given an Entity MyEntity below, the following code

EntityManagerFactory emf = Persistence.createEntityManagerFactory("greetingPU");
EntityManager em = emf.createEntityManager();

MyEntity e = new MyEntity(); 
e.setMessage1("hello"); e.setMessage2("world");
em.getTransaction().begin();
em.persist(e);
System.out.println("-- Before commit --");
em.getTransaction().commit();
System.out.println("-- After commit --");

results in an output indicating multiple calls to the "setter" methods of MyEntity by the EclipseLinks EntityManager or its associates. Is this behaviour to be expected? Possibly for some internal performance or structural reasons? Do other JPA implementations show the same behaviour?

-- Before commit --
setId
setId
setMessage1
setMessage2
setId
setMessage1
setMessage2
-- After commit --

There seem to be two different kinds of reassignments. First, an initial set of the Id. Second, two consecutive settings of the whole Entity. Debugging shows that all calls of a given "setter" have the same object as their parameter.

@Entity
public class MyEntity {

  private Long id;
  private String message1;
  private String message2;

  @Id
  @GeneratedValue(strategy=GenerationType.SEQUENCE)
  public Long getId(){ return id; }
  public void setId(Long i) { 
    System.out.println("setId");
    id = i;
  }

  public String getMessage1() { return message1; }
  public void setMessage1(String m) {
    message1 = m;
    System.out.println("setMessage1");
  }

  public String getMessage2() { return message2; }
  public void setMessage2(String m) {
    message2 = m;
    System.out.println("setMessage2");
  }
}

Solution

  • Are you using weaving? http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Weaving

    EclipseLink must call setId once to set the generated ID in the managed entity instance. It will also create an instance and set its values for the shared cache, explaining another setId and set values calls. If you are not using weaving, because the EntityManager still exists, EclipseLink will also create a backup instance to use to compare for future changes - any changes to the managed entity after the transaction commits still need tracked.

    If this isn't desirable, weaving allows attribute change tracking to be used instead so that backup copies aren't needed to track changes. You can also turn off the shared cache, but unless you are running into performance or stale data issues, this is not recommended.