-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Detached objects and session
PostPosted: Thu Aug 14, 2008 3:35 am 
Newbie

Joined: Mon Jul 14, 2008 7:08 am
Posts: 18
I have a lot of detached connected objects that I need to persist. The problem is that I can't pass them all, at one method call, to hibernate, because persisting is called by firing some events:

method Save
{
FireEvent1();
FireEvent2();
....
}

method Event1Handler()
{
SaveFirstDetachedPortionOfObjectGraph();
}

method Event2Handler()
{
SaveSecondDetachedPortionOfObjectGraph();
}
...

All these modifications are performed in different sessions so there are a lot of exceptions during persisting because each portion of objects is connected to each other. I can't see the way to resolve such synchronization problems.
On the other hand these problems are nothing if I perform persisting in one hibernate session. But I don't know how to do this...


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 14, 2008 4:25 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
What do you mean, you don't know how to use ONE Session?

Just make sure that for one Object Graph you have exactly one Session responsible for persisting that graph.

I don't understand where exactly is the problem?

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 14, 2008 4:53 am 
Newbie

Joined: Mon Jul 14, 2008 7:08 am
Posts: 18
schauder wrote:
I don't understand where exactly is the problem?

Suppose that you have two modules in your software. First module works with parent objects and second module works with child objects. Modules work independently and share information by sending events to each other (so they don't know about each other). At some moment you will have to persist changes made in each module and this moment comes when I fire events as I described in my first post. Each module has its own reference to hibernate and perform its own persisting. Because events are fired sequentially (and handlers can be executed in different threads) I can't save parents from first module and children from second modules in one session... This is the problem )))


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 14, 2008 10:48 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
From what you say the real problem is that the Session is tied to a Modul.

This is a very bad idea. A session is supposed to represent a Unit of Work. And for typical Modules there is no reason why a Unit of Work shouldn't span multiple Modules.

I see three options (you won't like either :-/ )

1. remove the link between modules and sessions. Identify the Unit of work and tie the session to it. This is the cleanest in most cases, but probably a large refactoring

2. Remove any Hibernate Reference that span multiple modules from your Objects. This would mean instead of

Code:
@ManyToOne
A myA


you would use

Long myA_id

And if you want the actual A you would retrieve the Session from the A-Module, request the session and use it to retrieve the correct A.

This is a big refactoring plus tons of boilerplate code for the rest of the lifetime of the software.

3. Write your own magic scheduler that aranges the changes due to be persisted in various sessions. This would be really challanging and probably would keep you busy until retirement (no matter how old you are right now).

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 14, 2008 9:16 pm 
Beginner
Beginner

Joined: Mon Feb 04, 2008 7:36 pm
Posts: 31
Quote:
3. Write your own magic scheduler that aranges the changes due to be persisted in various sessions. This would be really challanging and probably would keep you busy until retirement (no matter how old you are right now).


Well, I had a similar problem (not quite the same but similar). I implemented a method that scrapes all the object properties into a state collection, then connect in one session and push the data into objects retreived from the single session.

This method does require that you can some how intercept the call to the data store and cosolidate the work.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 15, 2008 2:36 am 
Newbie

Joined: Mon Jul 14, 2008 7:08 am
Posts: 18
schauder wrote:
remove the link between modules and sessions. Identify the Unit of work and tie the session to it.

I think this is the only reasonable way...
As far as I understand the simplest way to solve the problem should look like this (???):
method Save
{
var sessionId = HibernateServer.StartUnitOfWork(); // create session on server
FireEvent1(sessionId);
FireEvent2(sessionId);
HibernateServer.EndUnitOfWork(); // flush session
....
}

method Event1Handler(sessionId)
{
Save1(sessionId);
}

method Event2Handler(sessionId)
{
Save2(sessionId);
}

...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 15, 2008 6:55 am 
Newbie

Joined: Mon Jul 14, 2008 7:08 am
Posts: 18
schauder wrote:
remove the link between modules and sessions

Now I face another problem because only one session exists:
Because modules are independent from each other First module can delete parent object and all its children (due to cascade="all") and Second module can update some children of this parent BEFORE parent is removed. So when I accumulate changes in hibernate session I face the situation where child object is marked as deleted and the same child object (with the same identifier) comes with update.... and "a different object with the same identifier value was already associated with the session" exception occurs... What to do? )))

I tried to use Session.SaveOrUpdateCopy() to merge updates to deleted object but got an exception that object is deleted (actually transaction is still not ended). If I could somehow check that particular attached object is supposed to be deleted I could cancel any modifications of that object programmatically


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 15, 2008 12:07 pm 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
Quote:
Because modules are independent from each other First module can delete parent object and all its children (due to cascade="all") and Second module can update some children of this parent BEFORE parent is removed


I think there is still something seriously wrong with the whole setup.

If your modules are anything like the things I typically call modules, they should define:

- what objects exists
- what you can do to/with these objects

They should not at all influence the meaning of a Unit of Work.

If I understand you correctly your processflow looks like this:


Modul-A-process
- manipulate some A objects
End-A-process

Modul-B-process (concurrent to the process before)
- manipulate some B objects
End-B-process

Persistence Process
- Start Session
- take manipulated Objects from the processes before
- merge them into the session
- commit
- end Session
End Persistence Process

Since the A and B process do not talk to each other they might do things that contradict each other, causing problem in the Persistence Process.

So I'd try to move to a different model, more like this:

Single Process
- open Session
- attach object to session (no matter if from Module A or B)
- manipulate object as desired
- repeat as necessary
- commit
- end Session
End Process

I currently can't imagine why two processes should manipulate stuff which is supposed to belong to one Unit-Of-Work, at least not in the way you describe it.

If you really have to merge your objects from two sources into one session, try the following:

- check if the object is persistent (i.e. has an id), if not it's new great, persist.
- if it is, check if it is actually still in the database (load or get). If it isn't it's deleted, throw it away
- otherwise merge the state present in the session with the one you where about to put into the session.

Would you mind telling a little more about the kind of system you are trying to build? Web/RCP, Why this strange setup of modules ... I'm curious about what I am missing.

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 16, 2008 1:46 pm 
Newbie

Joined: Mon Jul 14, 2008 7:08 am
Posts: 18
schauder wrote:
If I understand you correctly your processflow looks like this

Yes, you understand me correctly

schauder wrote:
If your modules are anything like the things I typically call modules, they should define:

- what objects exists
- what you can do to/with these objects

Maybe it would be better to have another name instead of "module". I will try to explain later...
What if two modules define the same objects...

schauder wrote:
Since the A and B process do not talk to each other they might do things that contradict each other, causing problem in the Persistence Process

A little correction: they talk to each other by means of events. For example: current parent changed in module A -> module A fires event that current parent changed -> module B handles this event -> now current children in module B are children of current parent in module A.

schauder wrote:
Would you mind telling a little more about the kind of system you are trying to build?

It is simple winform smart client built on top of CAB (composite ui app block). Maybe I am building this system not in the way that CAB systems should be built, but I like the idea of what I have... I have simple generic view (user control) that can show me any type of object and allow me add/modify/delete these objects. View has controller and this controller can communicate to generic persistence layer. Also I have another generic view which allow user to work with collection of objects. This view also has controller. Having these views I can construct user interfaces for parent/children relationship very easily - just drop two user controls and code event publishing and subscribing (through cab event broker). Events allow modules (or workitems in cab terminology) to communicate. That's all for programmer who constructs this view - persistence code is already implemented (really not yet because I have problems ))) ) in each generic view/controller.
So it is obviously that "modules" don't know about each other but operate with the same data and I have to have two copies and then merge.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 18, 2008 1:07 am 
Newbie

Joined: Mon Jul 14, 2008 7:08 am
Posts: 18
schauder wrote:
- if it is, check if it is actually still in the database (load or get). If it isn't it's deleted, throw it away

Load and Get throw ObjectDeletedException ("The object with that id was deleted") when I try to update the state of deleted object when transaction is not still commited... Not very convenient ((( I'd prefer to get null


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 18, 2008 2:36 am 
Newbie

Joined: Mon Jul 14, 2008 7:08 am
Posts: 18
schauder wrote:
If you really have to merge your objects from two sources into one session, try the following:

- check if the object is persistent (i.e. has an id), if not it's new great, persist.
- if it is, check if it is actually still in the database (load or get). If it isn't it's deleted, throw it away
- otherwise merge the state present in the session with the one you where about to put into the session.

There is another conflict situation when I create parent and save it, add child to this parent and save it and then delete this parent in the same session. Though the cascade="all-delete-orphan" child is not deleted and constraint exception occurs. This is very ugly (((


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 19, 2008 2:49 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
dak565656 wrote:
Load and Get throw ObjectDeletedException ("The object with that id was deleted") when I try to update the state of deleted object when transaction is not still commited... Not very convenient ((( I'd prefer to get null



Not good

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 19, 2008 3:11 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
dak565656 wrote:
There is another conflict situation when I create parent and save it, add child to this parent and save it and then delete this parent in the same session. Though the cascade="all-delete-orphan" child is not deleted and constraint exception occurs. This is very ugly (((


I really think you are in a cul de sac and need to rethink the whole session handling structure. Otherwise the hole conflict handling problems will just kill you. Experience shows that the problems you currently have are probably just the tip of the iceberg

Establish a central point handing out the current session. make all modules use that session and communicate any changes immediatly so that the conflicting states can't emerge.

Don't know if a german text if of any help to you, anyway here is an article about the session handling in rich client applications

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 19, 2008 3:36 am 
Newbie

Joined: Mon Jul 14, 2008 7:08 am
Posts: 18
schauder wrote:
Otherwise the hole conflict handling problems will just kill you. Experience shows that the problems you currently have are probably just the tip of the iceberg

Yes it's true...

schauder wrote:
communicate any changes immediatly so that the conflicting states can't emerge

I agree with you. Looks like that this is the only way... On the other hand it would be nice and correct to implement conflict handling algorithm in persistence layer i.e. in hibernate. So hibernate should take everything and then before flushing check for conflicts... I don't think that this is very complex task

schauder wrote:
Don't know if a german text if of any help to you, anyway here is an article about the

will try to use babelfish )


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 28, 2008 6:24 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
I wrote a englisch version of my blog post about session handling in two tier rich client applications mentioned above.

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.