views:

438

answers:

3

I have an entity which looks something like this: (I'm coding to the web page so I apologize for any mistakes)

@Entity
public class Entity {
    @Id
    private Long id;
    private String field;

    // Insert getters and setters here...
}

I try to manipulate it using reflection:

Long id = 1;

Entity entity = myDao.getEntity(id);

entity.setField("set directly");

Field[] fields = entity.getClass().getDeclaredFields();

for (Field f : fields) {
    if (f.getName().equals("field")) {
        f.setAccessible(true);
        f.set(entity, "set using reflection");
        f.setAccessible(false);
    }
}

System.out.println(entity.getField());

This program prints "set using reflection". However, in the database the value set using reflection does not get updated:

SELECT * FROM ENTITY WHERE ID = 1
ID     FIELD
1      set directly

This is strange. I could swear that this used to work - but now it isn't. Is it really so that you cannot manipulate entities using reflection?

I'm using EclipseLink 1.1.1 if that matters.

A: 

Your class might be instrumented and the setters responsible for recording changes. I'm not familiar with EclipseLink to check if the class returned by myDao.getEntity(id); is your actual class of a sub-class generated by EclipseLink.

Robert Munteanu
+1  A: 

I'm pretty sure the Entity you are given by your persistence framework is actually wrapped in another class (possibly the same with stuff tacked on through reflection). Changing the field directly through reflection seems unlikely to work. You might want to check if there's a (generated) setter that you can use. Although if you're going that route one might ask why you don't allow callers to call the setter directly?

wds
Good question! The reason is that I'm trying to compare and update my entities using something like the answer I accepted on this one:http://stackoverflow.com/questions/867442/what-is-the-best-way-to-compare-several-javabean-properties
tputkonen
I'm not sure your design is very sane but if EclipseLink is modifying the class and adding setters it should be trivial to find them as they will probably follow the POJO conventions (setter for field is setField())
wds
See comment to Michael
tputkonen
+2  A: 

Changing values of an entity class by reflection is going to fraught with issues. This is because you're dealing with a class which is persistent and thus the persistence API needs to know about changes to the fields.

If you make changes via reflection, chances are the persistence API will not know about those changes.

A better solution would be to call the setters via reflection.

Michael Wiles
Thanks, now it works. I'm calling the setters and getters via reflection.I think the original code broke when EclipseLink's static weaving was turned on, because I'm sure manipulating the fields directly used to work.However, all is well now.
tputkonen