You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Simran Narula <sn...@avoka.com> on 2012/03/28 06:58:31 UTC

Track Column level changes in Cayenne

Hi,

I need to log each action taken on my portal UI for e.g.

Price changed for product x

Assume all the information is contained within one table i.e.both price & the product information.

When the portal is loaded with product information, user can change the price of the product.

I want to check if the price has changed or not and for that I am using a pre-update call back in Cayenne entity to check these changes, I want to check if the price x is changed to Y and push another history record in the Database. So far I have tried cache strategies - NO_CACHE and other workarounds but no success yet.

surely I can achieve this by other hacky means, but do not want to. My question is... is there any way to track column level changes in Cayenne ?

Thanks.
Simran



RE: Track Column level changes in Cayenne

Posted by Simran Narula <sn...@avoka.com>.
Don't worry about this !

The culprit was incorrect configuration in db


-----Original Message-----
From: Simran Narula [mailto:snarula@avoka.com] 
Sent: Tuesday, 10 April 2012 1:55 PM
To: user@cayenne.apache.org
Subject: RE: Track Column level changes in Cayenne

Hi Guys, 

Looks like need a little more help on below,

I am getting 

The INSERT statement conflicted with the FOREIGN KEY constraint "X_Constraint". The conflict occurred in database "MyDatabase", table "dbo.X", column 'X_oid'.

As raised earlier, I want to track column level changes on a particular entity, and for that Andrus advised me to get a parallel context and retrieve same object from the database and do the comparison Between the entity (that might have changed values) and fresh object that I have retrieved from the database using the parallel ObjectContext.

What I am doing is below,

On the save click on a page, I am saving the entity X like this:

myEntityService.save(X) 

// where save() just checks if it's a new object and registers it, otherwise just commits the changes using commitChanges();

Then, I have preUpdate() callback on X Entity Class, like this:

onPreUpdate() {
 if (hasPropertyValueChanged(properyNameConstant))
   {
    ObjectContext context = DataContext.getThreadObjectContext();
     Log l = (Log)context.newObject(Log.class);
     // populate log instance with whatever details
     addToLog(l);
   }
}

Where addToLog()... is simply addToManyTarget("Log", obj, true);

... and finally, I have the hasPropertyValueChanged is something like this...

hasPropertyValueChanged(String properyName) {
	
        ObjectContext parallelContext = DataContext.createDataContext(false);
        ObjEntity objEntity = parallelContext.getEntityResolver().lookupObjEntity(entityClass);

        String pkName = CayenneUtils.getPkName(entityClass);
        ObjectId objectId = new ObjectId(objEntity.getName(), pkName, pkId);

        ObjectIdQuery objectIdQuery = new ObjectIdQuery(objectId, false, ObjectIdQuery.CACHE_REFRESH);

        MyBaseEntity persistedObject = (MyBaseEntity) DataObjectUtils.objectForQuery(parallelContext, objectIdQuery);

        // Compare the value in the current entity object (where we suspect the value to might have changed of a particular column) and the persisted object that we just obtained
        // if the value has been changed then return true... allowing the new Log to be created...
} 


Once this is executed.. I get a 

The INSERT statement conflicted with the FOREIGN KEY constraint "X_Constraint". The conflict occurred in database "MyDatabase", table "dbo.X", column 'X_oid'.

Which eventually causes the 

CommitException... 

Why am I getting this... ? I know its complaining about foreign key constraint, on my X table which is represented by X entity in the code examples above, the Log table has a foreign key reference to X_oid in X Table


[Click] [error] handleException: org.apache.cayenne.CayenneRuntimeException: [v.3.0.2 Jun 11 2011 09:52:20] Commit Exception
	at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:1149)
	at org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:1060)
	at XXX.CayenneService.commitChanges(CayenneService.java:X)
	at XXX.EntityService.save(EntityService.java:X)
	at XXX.onSaveClick(MyPage.java:X)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at org.apache.click.util.ClickUtils.invokeListener(ClickUtils.java:1949)
	at org.apache.click.util.ActionListenerAdaptor.onAction(ActionListenerAdaptor.java:59)
	at org.apache.click.ActionEventDispatcher.fireActionEvent(ActionEventDispatcher.java:248)
	at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:193)
	at org.apache.click.ActionEventDispatcher$EventHolder.fireActionEvents(ActionEventDispatcher.java:430)
	at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:226)
	at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:212)
	at org.apache.click.ClickServlet.performOnProcess(ClickServlet.java:666)
	at org.apache.click.ClickServlet.processPage(ClickServlet.java:562)
	at org.apache.click.ClickServlet.handleRequest(ClickServlet.java:379)
	at org.apache.click.ClickServlet.doPost(ClickServlet.java:294)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at xxx
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at xxx
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	<...irrelevant lines truncated>
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at xxx
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:595)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The INSERT statement conflicted with the FOREIGN KEY constraint "X_Contraint". The conflict occurred in database "MyDatabase", table "dbo.X", column 'X_oid'.
	at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(Unknown Source)
	at com.microsoft.sqlserver.jdbc.IOBuffer.processPackets(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerStatement.sendExecute(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerStatement.doExecuteUpdate(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(Unknown Source)
	at org.apache.cayenne.access.jdbc.BatchAction.runAsIndividualQueries(BatchAction.java:221)
	at org.apache.cayenne.access.jdbc.BatchAction.performAction(BatchAction.java:91)
	at org.apache.cayenne.dba.sqlserver.SQLServerBatchAction.performAction(SQLServerBatchAction.java:59)
	at org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:87)
	at org.apache.cayenne.access.DataNode.performQueries(DataNode.java:269)
	at org.apache.cayenne.access.DataDomainFlushAction.runQueries(DataDomainFlushAction.java:226)
	at org.apache.cayenne.access.DataDomainFlushAction.flush(DataDomainFlushAction.java:144)
	at org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:824)
	at org.apache.cayenne.access.DataDomain$2.transform(DataDomain.java:791)
	at org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:850)
	at org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:788)
	at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:1121)
	... 65 more



-----Original Message-----
From: Simran Narula
Sent: Thursday, 5 April 2012 1:54 PM
To: 'user@cayenne.apache.org'
Subject: RE: Track Column level changes in Cayenne

Hey Andrus,

Thanks for your reply that day. 

Just wanted to let you know this Worked !!

Thanks heaps for help !

-----Original Message-----
From: Andrus Adamchik [mailto:andrus@objectstyle.org]
Sent: Wednesday, 28 March 2012 6:50 PM
To: user@cayenne.apache.org
Subject: Re: Track Column level changes in Cayenne

(reposting from stackoverflow answer)

There are a few ways to approach this. Here is the one that IMO is the most transparent. The trick is to use a different ObjectContext from the one committing changes. Then you will get a separate copy of the object that will contain currently saved value:

    // 'this' refers to the DataObject being committed (assuming things happen in its callback)
    
    ObjectContext parallelContext = ... // create a new context here like you normally would

    // 3.1 API; 3.0.x has a similar method with a slightly different sig
    MyClass clone = parallelContext.localObject(this);

    // if you are ok with cached old value, ignore the 'invalidateObjects' call.
    // If not, uncomment it to ensure the object gets refetched. 
    // Also 3.1 API. Should be easy to adjust for 3.0
    
    // parallelContext.invalidateObjects(clone);

    Object oldValue = clone.getXyz();

Andrus


On Mar 28, 2012, at 7:58 AM, Simran Narula wrote:

> Hi,
> 
> I need to log each action taken on my portal UI for e.g.
> 
> Price changed for product x
> 
> Assume all the information is contained within one table i.e.both price & the product information.
> 
> When the portal is loaded with product information, user can change the price of the product.
> 
> I want to check if the price has changed or not and for that I am using a pre-update call back in Cayenne entity to check these changes, I want to check if the price x is changed to Y and push another history record in the Database. So far I have tried cache strategies - NO_CACHE and other workarounds but no success yet.
> 
> surely I can achieve this by other hacky means, but do not want to. My question is... is there any way to track column level changes in Cayenne ?
> 
> Thanks.
> Simran
> 
> 


RE: Track Column level changes in Cayenne

Posted by Simran Narula <sn...@avoka.com>.
Hi Guys, 

Looks like need a little more help on below,

I am getting 

The INSERT statement conflicted with the FOREIGN KEY constraint "X_Constraint". The conflict occurred in database "MyDatabase", table "dbo.X", column 'X_oid'.

As raised earlier, I want to track column level changes on a particular entity, and for that Andrus advised me to get a parallel context and retrieve same object from the database and do the comparison 
Between the entity (that might have changed values) and fresh object that I have retrieved from the database using the parallel ObjectContext.

What I am doing is below,

On the save click on a page, I am saving the entity X like this:

myEntityService.save(X) 

// where save() just checks if it's a new object and registers it, otherwise just commits the changes using commitChanges();

Then, I have preUpdate() callback on X Entity Class, like this:

onPreUpdate() {
 if (hasPropertyValueChanged(properyNameConstant))
   {
    ObjectContext context = DataContext.getThreadObjectContext();
     Log l = (Log)context.newObject(Log.class);
     // populate log instance with whatever details
     addToLog(l);
   }
}

Where addToLog()... is simply addToManyTarget("Log", obj, true);

... and finally, I have the hasPropertyValueChanged is something like this...

hasPropertyValueChanged(String properyName) {
	
        ObjectContext parallelContext = DataContext.createDataContext(false);
        ObjEntity objEntity = parallelContext.getEntityResolver().lookupObjEntity(entityClass);

        String pkName = CayenneUtils.getPkName(entityClass);
        ObjectId objectId = new ObjectId(objEntity.getName(), pkName, pkId);

        ObjectIdQuery objectIdQuery = new ObjectIdQuery(objectId, false, ObjectIdQuery.CACHE_REFRESH);

        MyBaseEntity persistedObject = (MyBaseEntity) DataObjectUtils.objectForQuery(parallelContext, objectIdQuery);

        // Compare the value in the current entity object (where we suspect the value to might have changed of a particular column) and the persisted object that we just obtained
        // if the value has been changed then return true... allowing the new Log to be created...
} 


Once this is executed.. I get a 

The INSERT statement conflicted with the FOREIGN KEY constraint "X_Constraint". The conflict occurred in database "MyDatabase", table "dbo.X", column 'X_oid'.

Which eventually causes the 

CommitException... 

Why am I getting this... ? I know its complaining about foreign key constraint, on my X table which is represented by X entity in the code examples above, the Log table has a foreign key reference to X_oid in X Table


[Click] [error] handleException: org.apache.cayenne.CayenneRuntimeException: [v.3.0.2 Jun 11 2011 09:52:20] Commit Exception
	at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:1149)
	at org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:1060)
	at XXX.CayenneService.commitChanges(CayenneService.java:X)
	at XXX.EntityService.save(EntityService.java:X)
	at XXX.onSaveClick(MyPage.java:X)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at org.apache.click.util.ClickUtils.invokeListener(ClickUtils.java:1949)
	at org.apache.click.util.ActionListenerAdaptor.onAction(ActionListenerAdaptor.java:59)
	at org.apache.click.ActionEventDispatcher.fireActionEvent(ActionEventDispatcher.java:248)
	at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:193)
	at org.apache.click.ActionEventDispatcher$EventHolder.fireActionEvents(ActionEventDispatcher.java:430)
	at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:226)
	at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:212)
	at org.apache.click.ClickServlet.performOnProcess(ClickServlet.java:666)
	at org.apache.click.ClickServlet.processPage(ClickServlet.java:562)
	at org.apache.click.ClickServlet.handleRequest(ClickServlet.java:379)
	at org.apache.click.ClickServlet.doPost(ClickServlet.java:294)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at xxx
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at xxx
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	<...irrelevant lines truncated>
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at xxx
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:595)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The INSERT statement conflicted with the FOREIGN KEY constraint "X_Contraint". The conflict occurred in database "MyDatabase", table "dbo.X", column 'X_oid'.
	at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(Unknown Source)
	at com.microsoft.sqlserver.jdbc.IOBuffer.processPackets(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerStatement.sendExecute(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerStatement.doExecuteUpdate(Unknown Source)
	at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(Unknown Source)
	at org.apache.cayenne.access.jdbc.BatchAction.runAsIndividualQueries(BatchAction.java:221)
	at org.apache.cayenne.access.jdbc.BatchAction.performAction(BatchAction.java:91)
	at org.apache.cayenne.dba.sqlserver.SQLServerBatchAction.performAction(SQLServerBatchAction.java:59)
	at org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:87)
	at org.apache.cayenne.access.DataNode.performQueries(DataNode.java:269)
	at org.apache.cayenne.access.DataDomainFlushAction.runQueries(DataDomainFlushAction.java:226)
	at org.apache.cayenne.access.DataDomainFlushAction.flush(DataDomainFlushAction.java:144)
	at org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:824)
	at org.apache.cayenne.access.DataDomain$2.transform(DataDomain.java:791)
	at org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:850)
	at org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:788)
	at org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:1121)
	... 65 more



-----Original Message-----
From: Simran Narula 
Sent: Thursday, 5 April 2012 1:54 PM
To: 'user@cayenne.apache.org'
Subject: RE: Track Column level changes in Cayenne

Hey Andrus,

Thanks for your reply that day. 

Just wanted to let you know this Worked !!

Thanks heaps for help !

-----Original Message-----
From: Andrus Adamchik [mailto:andrus@objectstyle.org] 
Sent: Wednesday, 28 March 2012 6:50 PM
To: user@cayenne.apache.org
Subject: Re: Track Column level changes in Cayenne

(reposting from stackoverflow answer)

There are a few ways to approach this. Here is the one that IMO is the most transparent. The trick is to use a different ObjectContext from the one committing changes. Then you will get a separate copy of the object that will contain currently saved value:

    // 'this' refers to the DataObject being committed (assuming things happen in its callback)
    
    ObjectContext parallelContext = ... // create a new context here like you normally would

    // 3.1 API; 3.0.x has a similar method with a slightly different sig
    MyClass clone = parallelContext.localObject(this);

    // if you are ok with cached old value, ignore the 'invalidateObjects' call.
    // If not, uncomment it to ensure the object gets refetched. 
    // Also 3.1 API. Should be easy to adjust for 3.0
    
    // parallelContext.invalidateObjects(clone);

    Object oldValue = clone.getXyz();

Andrus


On Mar 28, 2012, at 7:58 AM, Simran Narula wrote:

> Hi,
> 
> I need to log each action taken on my portal UI for e.g.
> 
> Price changed for product x
> 
> Assume all the information is contained within one table i.e.both price & the product information.
> 
> When the portal is loaded with product information, user can change the price of the product.
> 
> I want to check if the price has changed or not and for that I am using a pre-update call back in Cayenne entity to check these changes, I want to check if the price x is changed to Y and push another history record in the Database. So far I have tried cache strategies - NO_CACHE and other workarounds but no success yet.
> 
> surely I can achieve this by other hacky means, but do not want to. My question is... is there any way to track column level changes in Cayenne ?
> 
> Thanks.
> Simran
> 
> 


RE: Track Column level changes in Cayenne

Posted by Simran Narula <sn...@avoka.com>.
By the way, Cayenne should allow checking if a particular value has been changed, may be in the future releases


-----Original Message-----
From: Simran Narula [mailto:snarula@avoka.com] 
Sent: Thursday, 5 April 2012 1:54 PM
To: user@cayenne.apache.org
Subject: RE: Track Column level changes in Cayenne

Hey Andrus,

Thanks for your reply that day. 

Just wanted to let you know this Worked !!

Thanks heaps for help !

-----Original Message-----
From: Andrus Adamchik [mailto:andrus@objectstyle.org] 
Sent: Wednesday, 28 March 2012 6:50 PM
To: user@cayenne.apache.org
Subject: Re: Track Column level changes in Cayenne

(reposting from stackoverflow answer)

There are a few ways to approach this. Here is the one that IMO is the most transparent. The trick is to use a different ObjectContext from the one committing changes. Then you will get a separate copy of the object that will contain currently saved value:

    // 'this' refers to the DataObject being committed (assuming things happen in its callback)
    
    ObjectContext parallelContext = ... // create a new context here like you normally would

    // 3.1 API; 3.0.x has a similar method with a slightly different sig
    MyClass clone = parallelContext.localObject(this);

    // if you are ok with cached old value, ignore the 'invalidateObjects' call.
    // If not, uncomment it to ensure the object gets refetched. 
    // Also 3.1 API. Should be easy to adjust for 3.0
    
    // parallelContext.invalidateObjects(clone);

    Object oldValue = clone.getXyz();

Andrus


On Mar 28, 2012, at 7:58 AM, Simran Narula wrote:

> Hi,
> 
> I need to log each action taken on my portal UI for e.g.
> 
> Price changed for product x
> 
> Assume all the information is contained within one table i.e.both price & the product information.
> 
> When the portal is loaded with product information, user can change the price of the product.
> 
> I want to check if the price has changed or not and for that I am using a pre-update call back in Cayenne entity to check these changes, I want to check if the price x is changed to Y and push another history record in the Database. So far I have tried cache strategies - NO_CACHE and other workarounds but no success yet.
> 
> surely I can achieve this by other hacky means, but do not want to. My question is... is there any way to track column level changes in Cayenne ?
> 
> Thanks.
> Simran
> 
> 


RE: Track Column level changes in Cayenne

Posted by Simran Narula <sn...@avoka.com>.
Hey Andrus,

Thanks for your reply that day. 

Just wanted to let you know this Worked !!

Thanks heaps for help !

-----Original Message-----
From: Andrus Adamchik [mailto:andrus@objectstyle.org] 
Sent: Wednesday, 28 March 2012 6:50 PM
To: user@cayenne.apache.org
Subject: Re: Track Column level changes in Cayenne

(reposting from stackoverflow answer)

There are a few ways to approach this. Here is the one that IMO is the most transparent. The trick is to use a different ObjectContext from the one committing changes. Then you will get a separate copy of the object that will contain currently saved value:

    // 'this' refers to the DataObject being committed (assuming things happen in its callback)
    
    ObjectContext parallelContext = ... // create a new context here like you normally would

    // 3.1 API; 3.0.x has a similar method with a slightly different sig
    MyClass clone = parallelContext.localObject(this);

    // if you are ok with cached old value, ignore the 'invalidateObjects' call.
    // If not, uncomment it to ensure the object gets refetched. 
    // Also 3.1 API. Should be easy to adjust for 3.0
    
    // parallelContext.invalidateObjects(clone);

    Object oldValue = clone.getXyz();

Andrus


On Mar 28, 2012, at 7:58 AM, Simran Narula wrote:

> Hi,
> 
> I need to log each action taken on my portal UI for e.g.
> 
> Price changed for product x
> 
> Assume all the information is contained within one table i.e.both price & the product information.
> 
> When the portal is loaded with product information, user can change the price of the product.
> 
> I want to check if the price has changed or not and for that I am using a pre-update call back in Cayenne entity to check these changes, I want to check if the price x is changed to Y and push another history record in the Database. So far I have tried cache strategies - NO_CACHE and other workarounds but no success yet.
> 
> surely I can achieve this by other hacky means, but do not want to. My question is... is there any way to track column level changes in Cayenne ?
> 
> Thanks.
> Simran
> 
> 


Re: Track Column level changes in Cayenne

Posted by Andrus Adamchik <an...@objectstyle.org>.
(reposting from stackoverflow answer)

There are a few ways to approach this. Here is the one that IMO is the most transparent. The trick is to use a different ObjectContext from the one committing changes. Then you will get a separate copy of the object that will contain currently saved value:

    // 'this' refers to the DataObject being committed (assuming things happen in its callback)
    
    ObjectContext parallelContext = ... // create a new context here like you normally would

    // 3.1 API; 3.0.x has a similar method with a slightly different sig
    MyClass clone = parallelContext.localObject(this);

    // if you are ok with cached old value, ignore the 'invalidateObjects' call.
    // If not, uncomment it to ensure the object gets refetched. 
    // Also 3.1 API. Should be easy to adjust for 3.0
    
    // parallelContext.invalidateObjects(clone);

    Object oldValue = clone.getXyz();

Andrus


On Mar 28, 2012, at 7:58 AM, Simran Narula wrote:

> Hi,
> 
> I need to log each action taken on my portal UI for e.g.
> 
> Price changed for product x
> 
> Assume all the information is contained within one table i.e.both price & the product information.
> 
> When the portal is loaded with product information, user can change the price of the product.
> 
> I want to check if the price has changed or not and for that I am using a pre-update call back in Cayenne entity to check these changes, I want to check if the price x is changed to Y and push another history record in the Database. So far I have tried cache strategies - NO_CACHE and other workarounds but no success yet.
> 
> surely I can achieve this by other hacky means, but do not want to. My question is... is there any way to track column level changes in Cayenne ?
> 
> Thanks.
> Simran
> 
>