refreshObject after commit causes problem for value change in the next transaction [message #1752206] |
Thu, 19 January 2017 16:17  |
Eclipse User |
|
|
|
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 #1753482 is a reply to message #1752917] |
Mon, 06 February 2017 19:43   |
Eclipse User |
|
|
|
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
|
|
|
|
Powered by
FUDForum. Page generated in 0.30141 seconds