You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Markus Reich <ma...@markusreich.at> on 2017/02/23 07:26:55 UTC

CommitChangesToParent() <> CommitChanges()

Hi,

I'm having some troubles understanding commitChanges() and
commitChangesToParent() :-/

I've created a test case with two ObjectContexts
ObjectContext context1 = runtime.newContext();
ObjectContext context2 = runtime.newContext();

then I load the same entity in both contexts
PpAfkoPordershead order1 = PpAfkoPordershead.getByAufnr(context1, 123);
PpAfkoPordershead order2 = PpAfkoPordershead.getByAufnr(context2, 123);

then I tried this
Integer quantity = order1.getQuantity();
order1.setQuantity(quantity + 1);
context1.commitChanges();
Assert.assertEquals(quantity, order2.getQuantity());

this works as the second context get synched by the commit.

but why does this work too?
Integer quantity = order1.getQuantity();
order1.setQuantity(quantity + 1);
context1.commitChangesToParent();
Assert.assertEquals(quantity, order2.getQuantity());

regards
Meex

Re: CommitChangesToParent() <> CommitChanges()

Posted by Hugi Thordarson <hu...@godurkodi.is>.
I don’t think this should be the case. Synchronization across contexts should only happen once objects have been committed to the DB. Running the following code generates the same output, regardless of whether OC synchronization is on or off:

	public static void main( String[] args ) {
		final String OLD_NAME = "Old Name";
		final String NEW_NAME = "New Name";

		final ObjectContext parentContext = HVCore.serverRuntime().newContext();
		final ObjectContext childContext1 = HVCore.serverRuntime().newContext( parentContext );
		final ObjectContext childContext2 = HVCore.serverRuntime().newContext( parentContext );
		final ObjectContext parentPeerContext = HVCore.serverRuntime().newContext();

		final User userInParent = User.fetchOne( parentContext, User.NAME.eq( OLD_NAME ) );
		final User userInChild1 = User.fetchOne( childContext1, User.NAME.eq( OLD_NAME ) );
		final User userInChild2 = User.fetchOne( childContext2, User.NAME.eq( OLD_NAME ) );
		final User userInParentPeer = User.fetchOne( parentPeerContext, User.NAME.eq( OLD_NAME ) );

		userInChild1.setName( NEW_NAME );

		childContext1.commitChangesToParent();

		System.out.println( "parent has: " + userInParent.name() );
		System.out.println( "child1 has: " + userInChild1.name() );
		System.out.println( "child2 has: " + userInChild2.name() );
		System.out.println( “parent peer has: " + userInParentPeer.name() );
	}

Output:

parent has: New Name
child1 has: New Name
child2 has: Old Name
parent peer has: Old Name

However, if I do a parentContext.commitChanges() (after committing changes from the child context) all objects will contain the same values.

Cheers,
- hugi



> On 23. feb. 2017, at 08:51, Musall, Maik <ma...@selbstdenker.ag> wrote:
> 
> Well, as long as you leave global synchronization enabled, it doesn't really matter in which context you commit something, because every change gets propagated everywhere. IMHO it doesn't make sense to use parent/child contexts with that setting at all.
> 
> Maik
> 
> 
>> Am 23.02.2017 um 09:38 schrieb Markus Reich <ma...@markusreich.at>:
>> 
>> Hi Maik,
>> 
>> thx for your detailed and quick answer! Ok the thing with the ChildContext
>> was my fault, although I should know better, shame on me :-/
>> But anyway the result of my test is the same.
>> 
>> What I can verifiy is that when you commit sthg to a context, the child
>> contexts gets synched immediatetly, when committing in childContext the
>> change is also immediately visible in the parent context, but in other
>> existing contexts.
>> 
>> As I see my testcase was not very usefull ;-)
>> 
>> regards
>> Meex
>> 
>> Musall, Maik <ma...@selbstdenker.ag> schrieb am Do., 23. Feb. 2017 um
>> 09:18 Uhr:
>> 
>>> Hi Markus,
>>> 
>>>> I'm having some troubles understanding commitChanges() and
>>>> commitChangesToParent() :-/
>>>> 
>>>> I've created a test case with two ObjectContexts
>>>> ObjectContext context1 = runtime.newContext();
>>>> ObjectContext context2 = runtime.newContext();
>>> 
>>> Those two don't have a parent/child relationship. For that you would have
>>> to create context2 = runtime.newContext( context1 );
>>> 
>>>> then I load the same entity in both contexts
>>>> PpAfkoPordershead order1 = PpAfkoPordershead.getByAufnr(context1, 123);
>>>> PpAfkoPordershead order2 = PpAfkoPordershead.getByAufnr(context2, 123);
>>>> 
>>>> then I tried this
>>>> Integer quantity = order1.getQuantity();
>>>> order1.setQuantity(quantity + 1);
>>>> context1.commitChanges();
>>>> Assert.assertEquals(quantity, order2.getQuantity());
>>>> 
>>>> this works as the second context get synched by the commit.
>>> 
>>> Btw, this synchronization is on by default, and can be switched off.
>>> Personally I can see the default changing some time in the future, because
>>> in multithreaded applications this can lead to difficult runtime problems
>>> when data that one thread is operating on changes mid-operation. For more
>>> details, see this chapter in the Cayenne Guide:
>>> https://cayenne.apache.org/docs/4.0/cayenne-guide/performance-tuning.html#turning-off-synchronization-of-objectcontexts
>>> <
>>> https://cayenne.apache.org/docs/4.0/cayenne-guide/performance-tuning.html#turning-off-synchronization-of-objectcontexts
>>>> 
>>> 
>>>> 
>>>> but why does this work too?
>>>> Integer quantity = order1.getQuantity();
>>>> order1.setQuantity(quantity + 1);
>>>> context1.commitChangesToParent();
>>>> Assert.assertEquals(quantity, order2.getQuantity());
>>> 
>>> Works the same because the parent is the same, see answer part #1. But
>>> that isn't what parent/child contexts are about anyway. The concept is more
>>> like if context2 is a child of context1, you could commit something in
>>> context2 to parent, and that would become visible in context1 as well, but
>>> wouldn't hit the database until you also commit in context1.
>>> 
>>> I'm fairly new to Cayenne as well, so if I got something wrong, I'm sure
>>> someone will correct me. :-)
>>> 
>>> Maik
>>> 
>>> 
> 


Re: CommitChangesToParent() <> CommitChanges()

Posted by "Musall, Maik" <ma...@selbstdenker.ag>.
Well, as long as you leave global synchronization enabled, it doesn't really matter in which context you commit something, because every change gets propagated everywhere. IMHO it doesn't make sense to use parent/child contexts with that setting at all.

Maik


> Am 23.02.2017 um 09:38 schrieb Markus Reich <ma...@markusreich.at>:
> 
> Hi Maik,
> 
> thx for your detailed and quick answer! Ok the thing with the ChildContext
> was my fault, although I should know better, shame on me :-/
> But anyway the result of my test is the same.
> 
> What I can verifiy is that when you commit sthg to a context, the child
> contexts gets synched immediatetly, when committing in childContext the
> change is also immediately visible in the parent context, but in other
> existing contexts.
> 
> As I see my testcase was not very usefull ;-)
> 
> regards
> Meex
> 
> Musall, Maik <ma...@selbstdenker.ag> schrieb am Do., 23. Feb. 2017 um
> 09:18 Uhr:
> 
>> Hi Markus,
>> 
>>> I'm having some troubles understanding commitChanges() and
>>> commitChangesToParent() :-/
>>> 
>>> I've created a test case with two ObjectContexts
>>> ObjectContext context1 = runtime.newContext();
>>> ObjectContext context2 = runtime.newContext();
>> 
>> Those two don't have a parent/child relationship. For that you would have
>> to create context2 = runtime.newContext( context1 );
>> 
>>> then I load the same entity in both contexts
>>> PpAfkoPordershead order1 = PpAfkoPordershead.getByAufnr(context1, 123);
>>> PpAfkoPordershead order2 = PpAfkoPordershead.getByAufnr(context2, 123);
>>> 
>>> then I tried this
>>> Integer quantity = order1.getQuantity();
>>> order1.setQuantity(quantity + 1);
>>> context1.commitChanges();
>>> Assert.assertEquals(quantity, order2.getQuantity());
>>> 
>>> this works as the second context get synched by the commit.
>> 
>> Btw, this synchronization is on by default, and can be switched off.
>> Personally I can see the default changing some time in the future, because
>> in multithreaded applications this can lead to difficult runtime problems
>> when data that one thread is operating on changes mid-operation. For more
>> details, see this chapter in the Cayenne Guide:
>> https://cayenne.apache.org/docs/4.0/cayenne-guide/performance-tuning.html#turning-off-synchronization-of-objectcontexts
>> <
>> https://cayenne.apache.org/docs/4.0/cayenne-guide/performance-tuning.html#turning-off-synchronization-of-objectcontexts
>>> 
>> 
>>> 
>>> but why does this work too?
>>> Integer quantity = order1.getQuantity();
>>> order1.setQuantity(quantity + 1);
>>> context1.commitChangesToParent();
>>> Assert.assertEquals(quantity, order2.getQuantity());
>> 
>> Works the same because the parent is the same, see answer part #1. But
>> that isn't what parent/child contexts are about anyway. The concept is more
>> like if context2 is a child of context1, you could commit something in
>> context2 to parent, and that would become visible in context1 as well, but
>> wouldn't hit the database until you also commit in context1.
>> 
>> I'm fairly new to Cayenne as well, so if I got something wrong, I'm sure
>> someone will correct me. :-)
>> 
>> Maik
>> 
>> 


Re: CommitChangesToParent() <> CommitChanges()

Posted by Markus Reich <ma...@markusreich.at>.
Hi Maik,

thx for your detailed and quick answer! Ok the thing with the ChildContext
 was my fault, although I should know better, shame on me :-/
But anyway the result of my test is the same.

What I can verifiy is that when you commit sthg to a context, the child
contexts gets synched immediatetly, when committing in childContext the
change is also immediately visible in the parent context, but in other
existing contexts.

As I see my testcase was not very usefull ;-)

regards
Meex

Musall, Maik <ma...@selbstdenker.ag> schrieb am Do., 23. Feb. 2017 um
09:18 Uhr:

> Hi Markus,
>
> > I'm having some troubles understanding commitChanges() and
> > commitChangesToParent() :-/
> >
> > I've created a test case with two ObjectContexts
> > ObjectContext context1 = runtime.newContext();
> > ObjectContext context2 = runtime.newContext();
>
> Those two don't have a parent/child relationship. For that you would have
> to create context2 = runtime.newContext( context1 );
>
> > then I load the same entity in both contexts
> > PpAfkoPordershead order1 = PpAfkoPordershead.getByAufnr(context1, 123);
> > PpAfkoPordershead order2 = PpAfkoPordershead.getByAufnr(context2, 123);
> >
> > then I tried this
> > Integer quantity = order1.getQuantity();
> > order1.setQuantity(quantity + 1);
> > context1.commitChanges();
> > Assert.assertEquals(quantity, order2.getQuantity());
> >
> > this works as the second context get synched by the commit.
>
> Btw, this synchronization is on by default, and can be switched off.
> Personally I can see the default changing some time in the future, because
> in multithreaded applications this can lead to difficult runtime problems
> when data that one thread is operating on changes mid-operation. For more
> details, see this chapter in the Cayenne Guide:
> https://cayenne.apache.org/docs/4.0/cayenne-guide/performance-tuning.html#turning-off-synchronization-of-objectcontexts
> <
> https://cayenne.apache.org/docs/4.0/cayenne-guide/performance-tuning.html#turning-off-synchronization-of-objectcontexts
> >
>
> >
> > but why does this work too?
> > Integer quantity = order1.getQuantity();
> > order1.setQuantity(quantity + 1);
> > context1.commitChangesToParent();
> > Assert.assertEquals(quantity, order2.getQuantity());
>
> Works the same because the parent is the same, see answer part #1. But
> that isn't what parent/child contexts are about anyway. The concept is more
> like if context2 is a child of context1, you could commit something in
> context2 to parent, and that would become visible in context1 as well, but
> wouldn't hit the database until you also commit in context1.
>
> I'm fairly new to Cayenne as well, so if I got something wrong, I'm sure
> someone will correct me. :-)
>
> Maik
>
>

Re: CommitChangesToParent() <> CommitChanges()

Posted by "Musall, Maik" <ma...@selbstdenker.ag>.
Hi Markus,

> I'm having some troubles understanding commitChanges() and
> commitChangesToParent() :-/
> 
> I've created a test case with two ObjectContexts
> ObjectContext context1 = runtime.newContext();
> ObjectContext context2 = runtime.newContext();

Those two don't have a parent/child relationship. For that you would have to create context2 = runtime.newContext( context1 );

> then I load the same entity in both contexts
> PpAfkoPordershead order1 = PpAfkoPordershead.getByAufnr(context1, 123);
> PpAfkoPordershead order2 = PpAfkoPordershead.getByAufnr(context2, 123);
> 
> then I tried this
> Integer quantity = order1.getQuantity();
> order1.setQuantity(quantity + 1);
> context1.commitChanges();
> Assert.assertEquals(quantity, order2.getQuantity());
> 
> this works as the second context get synched by the commit.

Btw, this synchronization is on by default, and can be switched off. Personally I can see the default changing some time in the future, because in multithreaded applications this can lead to difficult runtime problems when data that one thread is operating on changes mid-operation. For more details, see this chapter in the Cayenne Guide: https://cayenne.apache.org/docs/4.0/cayenne-guide/performance-tuning.html#turning-off-synchronization-of-objectcontexts <https://cayenne.apache.org/docs/4.0/cayenne-guide/performance-tuning.html#turning-off-synchronization-of-objectcontexts>

> 
> but why does this work too?
> Integer quantity = order1.getQuantity();
> order1.setQuantity(quantity + 1);
> context1.commitChangesToParent();
> Assert.assertEquals(quantity, order2.getQuantity());

Works the same because the parent is the same, see answer part #1. But that isn't what parent/child contexts are about anyway. The concept is more like if context2 is a child of context1, you could commit something in context2 to parent, and that would become visible in context1 as well, but wouldn't hit the database until you also commit in context1.

I'm fairly new to Cayenne as well, so if I got something wrong, I'm sure someone will correct me. :-)

Maik