-->
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.  [ 10 posts ] 
Author Message
 Post subject: Design issues with Hibernate and remote tree objects
PostPosted: Thu Nov 29, 2007 2:46 pm 
Newbie

Joined: Thu Nov 29, 2007 12:39 pm
Posts: 4
Hi. I'm developing in a 3 tier web application, using Hibernate for persistance. The presentation tier consists of Javascript RIA clients, which communicate with the business tier with tree-like remote objects (DTOs), which are then persisted with Hibernate. The root object of this tree is a Survey, and all business creations, modifications or deletions are made on a per-Survey basis.

I've encountered a couple of issues when developing such application, and I'de like to discuss them, to see if the solutions that I've applied are adequate and what alternatives there might be.

First, since the objects are remoted to Javascript, they cannot be lazy initialized. So my first ideia was to disable all lazy loading, however there are certain instances where I want to load an object without it's children (such as getting a list of all Surveys). So I left lazy loading on (in the mapping configuration), and when I want to load an object with all it's children, I simply walk the tree to force initialization of all elements. But is there a way to do this automatically in Hibernate? Or can we disable lazy loading in a given Hibernate query for a given mapping, overriding the mapping default?

Second, and most important, is the issue of object changes and DB updates, particularly with regards to orphans. If the tree objects were not remoted, I could use mappings with cascade="all-delete-orphans", and then have Hibernate's collections handle the updating of new elements and deletion of orphans. But that is not a possibility.
So one solution was to keep the old version of the survey (the root object) in the business tier, and whenever a new version of that object is requested to be saved, the old object is deleted by Hibernate, and a new one is created (effectively making each object tree immutable in the DB). This works since there are no references between surveys. It's not the most efficient but it is sufficient for the nature of the application.

If a more fine grained control is necessary (for example, because of performance reasons, or because references between survey trees would be necessary), what alternatives would there be? Perhaps using update() on the root objects with mappings with cascade="all", and then having the client maintain orphan lists? Can Hibernate help in any other way? Is version/timestamp useful here? (I have to say I haven't yet quite understood the uses for version/timestamp)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 13, 2007 10:27 am 
Newbie

Joined: Thu Dec 13, 2007 6:47 am
Posts: 2
Hi,

I have nearly the same problem, although my client is written in Flex. To initialize the children objects, I just call the initialize method.

However, this can't be the right solution for me because the relation between parents and children is of type many-to-many. So, loading an object could lead to loading the whole database.

I arrived to the conclusion that ORM + remote services is not completely possible with Hibernate (and probably with any such tool).

I am in the process of rewriting the application (a prototype in fact) with simple JDBC calls. I could use Hibernate to access each table, but this would in fact be overkill, compared to simple JDBC.

In my case (an application that manages meetings for persons, each person being related to several meetings and each meeting with several persons), The Hibernate version (without remote services) allows me to have only one DAO (for to get the list of persons). If I want to know the meetings related to one person, I can just ask this person. I can then select one of the meetings and ask this object for the other participants. Still no DAO.

In the remote version, this is not possible. When a remote client asks for the list of persons, I simply cannot load each person with the list of meetings, not even the list of meetings ids. So I need a meetingDAO that can return the list of meeting corresponding to a person Id to the remote service.

I know there are some frameworks to lazy load objects through a remote connection, but this is for Java remote client.

And frankly, I do not think automatic lazy loading is a good thing over remote connection. There are too many potential problems.

However, you can still use Hibernate to load your objects. You simply can't map the relations, which make ORM a bit less useful!

In short, in traditional applications, the domain layer is perpendicular to other layers and is accessible to all of them. It is, in particular, accessible to the presentation layer.

With remote client, this is not possible. At the very best, the domain objects appear to be accessible to the presentation layer, but through serialization. So, no lazy loading is possible. This is not a problem if your presentation layer is local like with JSPs, only remoting the views. You can't have remote clients manipulate domain objects. Only a static representation of these objects (at least with today's tools like Hibernate).

Pierre-Yves


Top
 Profile  
 
 Post subject: Issues with persistentset - deleting/re-creating collections
PostPosted: Wed Dec 19, 2007 5:01 pm 
Newbie

Joined: Wed Dec 19, 2007 4:42 pm
Posts: 3
We just came across a serious limitation in Hibernate especially in a distributed programming environment such as GWT-RPC or SOA.

In our scenario Hibernate is not able to recognize collection objects once they travel over network (serialized). So, it ends up deleting all the previous entries in the database and recreates them again based on the collection passed in.

We currently convert PersistentSet into HashSet and serialize it for sending to GWT client. When the same set come back to server for persistence, Hibernate is not able to recognize the objects in the HashSet. So, it ends up deleting all the entries and recreating them again. This is not acceptable behavior thus forcing us to manage Collections using custom coding efforts.

It appears this is a limitation in how the collections are implemented in Hibernate because it assumes all the objects or collection objects reside in the same JVM for their entire life. Whatever happened to the distributed computing such as SOA/CORBA/GWT-RPC??

Any simple work-around or a clean solution would be highly appreciated.
MA


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 20, 2007 10:29 am 
Newbie

Joined: Thu Dec 20, 2007 9:55 am
Posts: 2
Ok, I think I might be able to clear up a few things here.

Quote:
First, since the objects are remoted to Javascript, they cannot be lazy initialized. So my first ideia was to disable all lazy loading, however there are certain instances where I want to load an object without it's children (such as getting a list of all Surveys). So I left lazy loading on (in the mapping configuration), and when I want to load an object with all it's children, I simply walk the tree to force initialization of all elements. But is there a way to do this automatically in Hibernate? Or can we disable lazy loading in a given Hibernate query for a given mapping, overriding the mapping default?


I think you can use the FETCH keyword in your Hibernate queries to force initialization of lazy collections. So, for example, it should be possible to do the following...

Code:
from Cat as cat
    inner join fetch cat.mate


If you want to initialize all of the objects lazy associations, I believe you can use...

Code:
from Document fetch all properties


Please note that the above queries are taken directly from the Hibernate docs.

Quote:
Second, and most important, is the issue of object changes and DB updates, particularly with regards to orphans. If the tree objects were not remoted, I could use mappings with cascade="all-delete-orphans", and then have Hibernate's collections handle the updating of new elements and deletion of orphans. But that is not a possibility.
So one solution was to keep the old version of the survey (the root object) in the business tier, and whenever a new version of that object is requested to be saved, the old object is deleted by Hibernate, and a new one is created (effectively making each object tree immutable in the DB). This works since there are no references between surveys. It's not the most efficient but it is sufficient for the nature of the application.

If a more fine grained control is necessary (for example, because of performance reasons, or because references between survey trees would be necessary), what alternatives would there be? Perhaps using update() on the root objects with mappings with cascade="all", and then having the client maintain orphan lists? Can Hibernate help in any other way? Is version/timestamp useful here? (I have to say I haven't yet quite understood the uses for version/timestamp)


I'm gonna guess that your real problem here is the way you're implementing equals and/or hashcode. My experience with serializing Hibernate entities to a view has only been in the context of Jboss Seam, however... I've not had some of the difficulties you're describing. If my understanding is correct, Hibernate only knows that two objects are the same on two conditions. One is, if the session that initially fetched that object is still open. Two is, if the equals/hash-code methods tell Hibernate that the objects are equivalent.

However, in the case of remoting, I believe that even if the session were to remain open, you'd still end up with Hibernate being unable to tell that the objects were the same unless you had a good equals/hash-code implementation.

Quote:
Hi,

I have nearly the same problem, although my client is written in Flex. To initialize the children objects, I just call the initialize method.

However, this can't be the right solution for me because the relation between parents and children is of type many-to-many. So, loading an object could lead to loading the whole database.

I arrived to the conclusion that ORM + remote services is not completely possible with Hibernate (and probably with any such tool).


Have you looked into EJB3 using Hibernate as your implementation? The reason I ask is because it seems well suited to trying to combine remote services + ORM. However, I think you may have some confusion as to exactly what you're trying to accomplish. The lazy/eager fetching issue isn't native to remote applications at all. Any time you fetch data now, and access it later you can have the issue you're describing.

Quote:
In my case (an application that manages meetings for persons, each person being related to several meetings and each meeting with several persons), The Hibernate version (without remote services) allows me to have only one DAO (for to get the list of persons). If I want to know the meetings related to one person, I can just ask this person. I can then select one of the meetings and ask this object for the other participants. Still no DAO.

In the remote version, this is not possible. When a remote client asks for the list of persons, I simply cannot load each person with the list of meetings, not even the list of meetings ids. So I need a meetingDAO that can return the list of meeting corresponding to a person Id to the remote service.


Sounds like there should be a way to do this without requiring the creation of a MeetingDAO (even though I'm not sure that's such a bad thing). You have a bi-directional @ManyToMany association between Meeting and Person from what I'm gathering... but why do both sides have to be fetch=FetchType.EAGER. Since it sounds like your remote client _always_ needs the meeting data for people that it has, make Person->Meeting eagerly fetched, and make Meeting->Person lazily fetched. Then, if you're absolutely desperate to actually ask a Meeting for all of the people involved you can invoke a remote method to get this information.

No matter what technology you choose, you can't have your cake and eat it too. If you need all of the information up front, then you have to accept the cost that comes with that. If you need it later, it needn't function any differently than a web application in that it must make a request of the data provider to get the additional info as needed.

Quote:
I know there are some frameworks to lazy load objects through a remote connection, but this is for Java remote client.

And frankly, I do not think automatic lazy loading is a good thing over remote connection. There are too many potential problems.


Then, as suggested above, do it manually.

Quote:
However, you can still use Hibernate to load your objects. You simply can't map the relations, which make ORM a bit less useful!


Huh? You seem to be contradicting yourself. Do you want Hibernate to fetch associations remotely or not?

Quote:
In short, in traditional applications, the domain layer is perpendicular to other layers and is accessible to all of them. It is, in particular, accessible to the presentation layer.

With remote client, this is not possible. At the very best, the domain objects appear to be accessible to the presentation layer, but through serialization. So, no lazy loading is possible. This is not a problem if your presentation layer is local like with JSPs, only remoting the views. You can't have remote clients manipulate domain objects. Only a static representation of these objects (at least with today's tools like Hibernate).


EJB3 with Hibernate as it's implementation allows you to do just that. Furthermore, you can have this exact same problem with JSP's deployed on the same box as your Hibernate domain objects. Yes, there are limitations to using ORM, but I don't believe the ones you're pointing out as specific to remoting are really all that different from the generic problems of an ORM.

Quote:
We just came across a serious limitation in Hibernate especially in a distributed programming environment such as GWT-RPC or SOA.

In our scenario Hibernate is not able to recognize collection objects once they travel over network (serialized). So, it ends up deleting all the previous entries in the database and recreates them again based on the collection passed in.

We currently convert PersistentSet into HashSet and serialize it for sending to GWT client. When the same set come back to server for persistence, Hibernate is not able to recognize the objects in the HashSet. So, it ends up deleting all the entries and recreating them again. This is not acceptable behavior thus forcing us to manage Collections using custom coding efforts.

It appears this is a limitation in how the collections are implemented in Hibernate because it assumes all the objects or collection objects reside in the same JVM for their entire life. Whatever happened to the distributed computing such as SOA/CORBA/GWT-RPC??

Any simple work-around or a clean solution would be highly appreciated.
MA


Look at the EQUALS/HASH-CODE of your beans. Hibernate only assures you that an == test will work as long as the session that the object was fetched in is still open (and being used here, obviously). For other cases, you have to describe to Hibernate how to tell if two objects really represent the same thing. This is no different from any other distributed app. If you serialize an object and then de-serialize it, == will no longer function. It's up to you to ensure that the equals method of your object will be able to point the JVM in the correct direction in these cases.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 09, 2008 2:30 pm 
Newbie

Joined: Thu Nov 29, 2007 12:39 pm
Posts: 4
peewhy wrote:
Hi,

I have nearly the same problem, although my client is written in Flex. To initialize the children objects, I just call the initialize method.

However, this can't be the right solution for me because the relation between parents and children is of type many-to-many. So, loading an object could lead to loading the whole database.

I arrived to the conclusion that ORM + remote services is not completely possible with Hibernate (and probably with any such tool).

I am in the process of rewriting the application (a prototype in fact) with simple JDBC calls. I could use Hibernate to access each table, but this would in fact be overkill, compared to simple JDBC.

Yes, if you have a many-to-many relation, you be able to do it in the same way I did. Still, I don't understand why you're switching to JDBC and ditching Hibernate: you may not be able to use all of the funtionality of Hibernate (like managing orphans), but you can still use it for the rest (Object Relational mapping).
Namely, in your case (if I understood it correcly) I think I would do it like this: Use Hibernate and have all (or most of) the relations lazy loaded. Have in the remoting client a way to detect if such an association has been loaded or not. Whenever such association in the client is accessed, have it detect whether it's initialized or not, if not, make a call to a DAO in the server to fill out the collection (by means of Hibernate), and return the object with the filled collection. Basicly you do the lazy loading manually instead of having Hibernate do it automatically. If the client also changes its domains objects instead of just reading them, you will also have to do something like object deletion detection manually (orphan lists), and keep the server correctly informed of such changes.
This increases the complexity in the client, sure, but it seems it's something you have to do either way, either with Hibernate or with JDBC. But with Hibernate at least you have some things done for you (the SQL mappings, DB transparency/portability, etc.). I may not have fully understood your problem tough.

bkyrlach wrote:
Ok, I think I might be able to clear up a few things here.

Quote:
First, since the objects are remoted to Javascript, they cannot be lazy initialized. So my first ideia was to disable all lazy loading, however there are certain instances where I want to load an object without it's children (such as getting a list of all Surveys). So I left lazy loading on (in the mapping configuration), and when I want to load an object with all it's children, I simply walk the tree to force initialization of all elements. But is there a way to do this automatically in Hibernate? Or can we disable lazy loading in a given Hibernate query for a given mapping, overriding the mapping default?


I think you can use the FETCH keyword in your Hibernate queries to force initialization of lazy collections. So, for example, it should be possible to do the following...

Code:
from Cat as cat
    inner join fetch cat.mate


If you want to initialize all of the objects lazy associations, I believe you can use...

Code:
from Document fetch all properties


Please note that the above queries are taken directly from the Hibernate docs.


I tried that initially, but it doesn't work: FETCH initializes the collection of the first (top-level) object only, but the objects inside that collection remain with lazy collections. FETCH doesn't work transitively.
The workaround is pretty simple tough, just iterate and recurse (while inside the Hibernate session) on all associations you want loaded, and they will be initialized.

bkyrlach wrote:
Quote:
Second, and most important, is the issue of object changes and DB updates, particularly with regards to orphans. If the tree objects were not remoted, I could use mappings with cascade="all-delete-orphans", and then have Hibernate's collections handle the updating of new elements and deletion of orphans. But that is not a possibility.
So one solution was to keep the old version of the survey (the root object) in the business tier, and whenever a new version of that object is requested to be saved, the old object is deleted by Hibernate, and a new one is created (effectively making each object tree immutable in the DB). This works since there are no references between surveys. It's not the most efficient but it is sufficient for the nature of the application.

If a more fine grained control is necessary (for example, because of performance reasons, or because references between survey trees would be necessary), what alternatives would there be? Perhaps using update() on the root objects with mappings with cascade="all", and then having the client maintain orphan lists? Can Hibernate help in any other way? Is version/timestamp useful here? (I have to say I haven't yet quite understood the uses for version/timestamp)


I'm gonna guess that your real problem here is the way you're implementing equals and/or hashcode. My experience with serializing Hibernate entities to a view has only been in the context of Jboss Seam, however... I've not had some of the difficulties you're describing. If my understanding is correct, Hibernate only knows that two objects are the same on two conditions. One is, if the session that initially fetched that object is still open. Two is, if the equals/hash-code methods tell Hibernate that the objects are equivalent.

However, in the case of remoting, I believe that even if the session were to remain open, you'd still end up with Hibernate being unable to tell that the objects were the same unless you had a good equals/hash-code implementation.



No, not really, it doesn't have to do with equals and/or hashcode.
In the basic case, Hibernate can detect changes (updates) of the same object, since you have an object with a given id, and it will simply update the corresponding row in the table (or something like that). Additions are detected by objects that have a null id. But object removals can not be detected normally: Hibernate requires the removals to happen in Hibernate collections (PersistentSet, PersistentList, etc.). so that they can manage orphans(deletions in a collection) automatically (ie, keep a list a of ids of deleted objects).
If you cannot use Hibernate's collections (because you're across a remoting/application boundary), you will have to manage orphans manually in some kind of way, or you will have an inconsistent DB.
This is my understanding of Hibernate, I think it is correct (but I'm still a noob tough).


Top
 Profile  
 
 Post subject: Re: Issues with persistentset - deleting/re-creating collect
PostPosted: Wed Jan 09, 2008 2:43 pm 
Newbie

Joined: Thu Nov 29, 2007 12:39 pm
Posts: 4
mamasa wrote:
We just came across a serious limitation in Hibernate especially in a distributed programming environment such as GWT-RPC or SOA.

In our scenario Hibernate is not able to recognize collection objects once they travel over network (serialized). So, it ends up deleting all the previous entries in the database and recreates them again based on the collection passed in.

We currently convert PersistentSet into HashSet and serialize it for sending to GWT client. When the same set come back to server for persistence, Hibernate is not able to recognize the objects in the HashSet. So, it ends up deleting all the entries and recreating them again. This is not acceptable behavior thus forcing us to manage Collections using custom coding efforts.

It appears this is a limitation in how the collections are implemented in Hibernate because it assumes all the objects or collection objects reside in the same JVM for their entire life. Whatever happened to the distributed computing such as SOA/CORBA/GWT-RPC??

Any simple work-around or a clean solution would be highly appreciated.
MA


The basic solution is like you said, delete the whole old collection, and create the whole new collection. This works correctly if you don't have external references to elements inside the collection, but is of course, less than ideal in terms of performance. The only improvement I can see, is to enhance the client, so that it maintains a list of orphans as mentioned in my last post. Then the server updates the collection by deleting the orphans, and calling session.update() on the new collection object.

Another possible alternative: if the client side of remoting is also Java, and also has Hibernate, I wonder if it is possible to serialize the PersistentSet collections and have them manage the orphans in the client side? I think some people have tried this but I don't know the result. (not possible in any way in my remoting setup, since the client side is Javascript).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 15, 2008 10:24 am 
Newbie

Joined: Thu Dec 13, 2007 6:47 am
Posts: 2
First, I want to thank brunomeideros and bkyrlach for their answers, both very helpful to help me understand all specificities of the problem.

The solution described by brunomeideros looks fine, although there are somme other issues :

The main isssue is that the tool I use for remoting won't serialize objects enhanced by Hibernate for lazy loading. I am fine with remoting uninitialized objects. I can simply test properties for null and fetch them when needed. But as uninitialized object won't be remoted, no chance!

Wheter they are initialized or not, my objects are reported by my debugger to be from a different class (enhanced by CGLIB).

I tried to set hibernate.bytecode.use_reflection_optimizer=false but this does not help. an object of class User, for example, is reported to be of class User$$EnhancedByCGLIB$$1feac9c1. The only way to get it with the correct class is to turn of lazy loading.

So the question is : how can I send remotly an object with an unitialized property while retaining the correct class (and not "enhanced" one) for this object ?


Top
 Profile  
 
 Post subject: Re: Design issues with Hibernate and remote tree objects
PostPosted: Mon Jul 12, 2010 3:34 am 
Newbie

Joined: Mon Jul 12, 2010 3:02 am
Posts: 4
If you want to send s remotly an object with an unitialized property so I have one site name This site has to provide your problem solution."forums.adobe" dot com

_________________
Website Marketing New York


Top
 Profile  
 
 Post subject: Re: Design issues with Hibernate and remote tree objects
PostPosted: Mon Jul 26, 2010 3:21 am 
Newbie

Joined: Mon Jul 26, 2010 3:15 am
Posts: 4
There are so many things which can be uses for the hibernate and remote tree objects such as remotly to send an object with a property that has not been initialized so I have a site name of this site is to provide the solution to the problem. "Forums.adobe dot com.

_________________
voucher codes argos


Top
 Profile  
 
 Post subject: Re: Design issues with Hibernate and remote tree objects
PostPosted: Mon Sep 06, 2010 3:53 am 
Newbie

Joined: Mon Sep 06, 2010 3:21 am
Posts: 5
I read your post and all replay and you post very nice information. and actually I dont know about its all this utility and its features and because of your post I know it and its really increase my knowledge.

_________________
package holidays


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 

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.