Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » refreshObject after commit causes problem for value change in the next transaction
refreshObject after commit causes problem for value change in the next transaction [message #1752206] Thu, 19 January 2017 21:17 Go to next message
Ye Huang is currently offline Ye HuangFriend
Messages: 3
Registered: January 2017
Junior Member
Recently we migrated our code from Toplink to EclipseLink2.6.2. We noticed some functions that used to work in Toplink stopped working. Here is a simplified version of the code:

Session clientSession = ServiceFactory.getClient().newClientSession();
ExpressionBuilder builder = new ExpressionBuilder();
DCForm form = (DCForm)clientSession.readObject(com.clickfind.dataCollector.DCForm.class, builder.get("id").equal(422463));

DCQuestion question = null;

for (DCQuestion q : form.getQuestions()) {
if (q.getAlias().equals("siteName")) {
question = q;
break;
}
}
UnitOfWork unitOfWork = clientSession.acquireUnitOfWork();
DCQuestion questionClone = (DCQuestion)unitOfWork.registerObject(question);
String timeValue = String.valueOf(System.currentTimeMillis());
questionClone.setValue(timeValue);
DCForm formClone = (DCForm)unitOfWork.registerObject(form);
formClone.getQuestions();
unitOfWork.commit();
clientSession.refreshObject(form);


With the refreshObject(form) call, if we execute this set of code after the first run, no change will be saved to database. We found out it is because formClone.getQuestions() overwrites the modified question value in the unit of work with cached question value. If we remove the refreshObject call, then question values will be saved properly.

DCForm has a OneToMany relationship to the DCQuestions

oneToManyMapping = new OneToManyMapping();
oneToManyMapping.setAttributeName("questions");
oneToManyMapping.setReferenceClass(DCQuestion.class);
oneToManyMapping.setTargetForeignKeyFieldName("DCQUESTION.FORMID");
oneToManyMapping.useCollectionClass(GeneralClickList.class);
oneToManyMapping.setIsPrivateOwned(true);
oneToManyMapping.setGetMethodName("getQuestionsHolder");
oneToManyMapping.setSetMethodName("setQuestionsHolder");
descriptor.addMapping(oneToManyMapping);


Are we using the methods incorrectly or is this a problem in EclipseLink?
Re: refreshObject after commit causes problem for value change in the next transaction [message #1752917 is a reply to message #1752206] Mon, 30 January 2017 16:21 Go to previous messageGo to next message
Ye Huang is currently offline Ye HuangFriend
Messages: 3
Registered: January 2017
Junior Member
We find out when refreshObject is called on the form object, the QueryBasedValueHolder for questions has the refreshIdentityMapResult flag set as true. Then when the form is registered in the UnitOfWork, the questions value holder of the new cloned form object also has the refreshIdentityMapResult flag set as true. So when formClone.getQuestions is executed, the question objects that already have been registered in the unit of work are replaced no matter if they have been modified or not.
Should this be a bug?
Re: refreshObject after commit causes problem for value change in the next transaction [message #1753482 is a reply to message #1752917] Tue, 07 February 2017 00:43 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1275
Registered: July 2009
Senior Member
I haven't seen the native API used in a while, so I'm not quite sure the setting you might use to change the behavior, but the issue is to be expected. Setting private ownership in native EclipseLink api would cause the equivalent of JPA's cascade options over the relationship when using the native api methods, such as refreshObject on the client session. This means that when refreshing the object, the indirection is reset and when triggered, refreshes the referenced object as you've seen.

The problem here is that you are using refreshObject on the ClientSession, a convenience method for:
public Object refreshAndLockObject(Object object, short lockMode) throws DatabaseException {
        ReadObjectQuery query = new ReadObjectQuery();
        query.setSelectionObject(object);
        query.refreshIdentityMapResult();
        query.cascadePrivateParts();
        query.setLockMode(lockMode);
        query.setIsExecutionClone(true);
        return executeQuery(query);
    }



The problem is with the cascadePrivateParts() setting. You will want to create an execute your own query leaving that part out, or calling dontCascadeParts() on it to prevent the refresh from cascading to privately owned references when the indirection is triggered.

An alternative solution is to trigger the reference upfront, by calling getQuestions(); immediately after the refresh.

Best Regards,
Chris
Re: refreshObject after commit causes problem for value change in the next transaction [message #1753588 is a reply to message #1753482] Tue, 07 February 2017 22:58 Go to previous message
Ye Huang is currently offline Ye HuangFriend
Messages: 3
Registered: January 2017
Junior Member
Chris,

Thank you. We have decided to not set cascadePrivateParts when refreshing the object.

[Updated on: Tue, 07 February 2017 22:59]

Report message to a moderator

Previous Topic:Cache coordination using jgroups using UDP unicast, is it possible
Next Topic:Problems with aggregate collection mappings
Goto Forum:
  


Current Time: Thu Dec 14 02:15:05 GMT 2017

Powered by FUDForum. Page generated in 0.01863 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software