Daniele Licitra
Daniele Licitra

Reputation: 1608

JPA entity modified by reflection not merged by entity manager

I need to check if my actual entity is different from the old one.

I use reflection because my method must be standardized.

For each column, I update the value if and only if it's not null (because i read it from a CSV and a column may be not specified).

for(Field column : fields){
   column.setAccessible(true);
   Object newValue = column.get(myObject);
   if( newValue != null && !newValue.equals(column.get(oldObject))){
      column.set(oldObject, newValue);
   }
}

this.entitymanager.merge(oldObject)

If I do the changes like that, no UPDATE query is done.

If I change the value in the normal way oldobject.setValue(newValue) the query is done and the record is updated.

Why no UPDATE query is done by the entity manager if I change value via reflection?

Upvotes: 1

Views: 530

Answers (2)

Daniele Licitra
Daniele Licitra

Reputation: 1608

Thank to @Ken Chan answer, I correct the method using getters and setters.

for(Field column : columns){
   Method mSet = myclass.getMethod("set"+ StringUtils.capitalize(column.getName()), column.getType());
   Method mGet = myclass.getMethod("get"+ StringUtils.capitalize(column.getName()));
   Object newValue = mGet.invoke(articolo);
   if( newValue != null && !newValue.equals(mGet.invoke(old))){
        mSet.invoke(old, newValue);
   }
 }

I must pay attention to methods' name. If entity have the property description, there must be also getDescription() and setDescription().

Now it works

Upvotes: 0

Ken Chan
Ken Chan

Reputation: 90427

Just find some good information about such behaviour at this :

By default when using weaving/agent EclipseLink uses attribute change tracking to detect changes. This will not detect changes made through reflective field access (method access is ok though).

You can change the default using the @ChangeTracking annotation to deferred which will detect change made through reflection. i.e. @ChangeTracking(ChangeTrackingType.DEFERRED)

You could also disable weaving, or weaving of change tracking in the persistence.xml using, "eclipselink.weaving.changetracking"="false"

So there are couple of solutions that can try :

  1. Use reflective method access
  2. Change the ChangeTracking to deferred or even disable it
  3. Disable weaving

Upvotes: 2

Related Questions