public B getBType() {
if (b_type == null && B_id != 0) {
b_type = readSingleEntityById(B.class, B_id);
}
return b_type;
}
public void setBType(B ent) {
b_type = ent;
if (b_type != null)
B_id = b_type.getId();
else
B_id = getBTypeId();
}
public Integer getBTypeId() {
if (B_id == 0 && getBType() != null)
B_id = b_type.getId();
return B_id;
}
@Override
public SerializableEntity copy() {
return new A(this);
}
public A() {
}
public Integer getId() {
if (id == null) {
return 0;
} else {
return id;
}
}
public void setId(Integer id) {
this.id = id;
}
}
public void saveA(){
try {
UserTransaction u = getUserTransaction();
u.begin();
u.merge(A);
u.commit();
} catch {
code here to catch exception
}
}
public <T> T merge(T ent) {
ent = m_em.merge(ent); ----> Problem
m_em.flush();
addMergedEntityToMyCache(ent);
return ent;
}
I have two entities A and B defined as above. A has a many-to-one relationship to Entity B.
Old Values -
b_id = 2
b_type = obj2_type.
New Values to merge. When I enter the merge method these are correct values for ent object
b_id = 4
b_type = obj4_type.
After the call to m_em.merge() the values in the Entity A are -
b_id = 2
b_type = obj4_type
The database is updated with the correct values. Disabling shared cache does not fix the problem. What am I doing wrong here ? Is the b_id as Transient an issue ?. If yes why ? I shouldn't be getting back stale id but the correct merged entity object.
Just to clarify above - The behavior I see is that my transient id that is id of the referenced entity in Class A seem to retain old value while the actual referenced entity gets updated after merge. How do I keep the transient id and object in-sync. Any ideas ?
Yes, Transient is the problem. Because B_ID is transient, it is not merged or persisted to the database in anyway: it is as if it doesn't exist to JPA.
What is the point of keeping b_id in the entity when you are keeping a reference to B itself? Since the field exists, you might want to remove the @Transient and map it to the "B_ID" field but make it insertable=false, updateable=false so that the ManyToOne still controls the field. Or you can look into post merge events which can be used to fix transient fields after the merge.
Thanks Chris. I am going to add postMerge event and do some testing. We are keeping the b_id so that we can serialize/deserialize it and send it to the Client instead of the entire object. Is this a good way to go about it or you have a better suggestion ?