-->
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: Can DTOs reference specified parts of the object graph??
PostPosted: Tue Mar 30, 2004 10:28 am 
Regular
Regular

Joined: Fri Nov 07, 2003 6:31 am
Posts: 104
Location: Beijing, China
Hi everyone,

We're building a Velocity-Struts web app with Hibernate and Spring.

I'm actually having an argument with one of my team member who refuses to instanciate dedicated presentation data container and keeps referencing Hibernate persistent objects (or specified parts of the object graph) in his ActionForms. His main argument is that ActionForm aren't actually part of the view but of the controller layer. (he's right, it's stated in the Struts doc) And it's very convenient since he's able to simply access the object attributes directly via Velocity.

It was not really a problem up to now, but since I customized the hibernate mapping to make heavy use of the lazy initialization, we got lots of lazy init. exception when velocity tries to access a lazy collection.

So is my first question: why Struts cannot lazy initialize the collection? (I think this happens when doing mapping.findForward("somewhere") so it should have the Spring context and be able to)

And do you guys know good reasons not to reference specified parts of the object graph in DTO? (apart from the fact that you can't lazy initialize collection in DTOS :-) )


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 30, 2004 2:10 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
Quote:
why Struts cannot lazy initialize the collection?


certainly because you're using threadlocal strategy and so because the session is closed between mapping.findForward("somewhere") and the view.

You should not think using "lazy options" higher than your application layer on your architecture, this would mean you let your pages hit an "open" hibernate session and this is evil ...

Quote:
And do you guys know good reasons not to reference specified parts of the object graph in DTO


look at
http://forum.hibernate.org/viewtopic.php?t=929459

there are many differents points of view about DTO, you may find args to use or not DTO on your app

Anthony


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 30, 2004 2:35 pm 
Regular
Regular

Joined: Wed Mar 03, 2004 9:38 am
Posts: 70
Take a look at the org.springframework.orm.hibernate.support.OpenSessionInViewFilter class. When using it the session is closed after the view has been rendered and thus lazy loading will work.

Note that using the open session in view pattern does change the transaction semantics of you application somewhat. My understanding is that lazy loads in the view will execute non-transactionally, so if that is a problem for you, you have to find some other approach (e.g. Hibernate.initialize() in your DAO methods). Personally, I don't think it's a big deal, since the lazy loads are read-only anyway.

Or does anyone have a good explanation as to why read-only operations should be executed inside a transaction?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 30, 2004 2:37 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
to manage the locks...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 30, 2004 4:48 pm 
Regular
Regular

Joined: Wed Mar 03, 2004 9:38 am
Posts: 70
delpouve wrote:
to manage the locks...


Uh, but what about databases that use multiple versioning instead of read locks?

Anyways, the database has to do the locking correctly regardless if the operation is executed in a transaction or not, otherwise one might corrupt the database.

I did some googling around, and I found a manual for Oracle 9, which is a database that uses MVCC instead of read locks. What that manual tells about READ ONLY transactions is:

Quote:
All subsequent queries in that transaction only see changes committed before the transaction began. Read-only transactions are useful for reports that run multiple queries against one or more tables while other users update these same tables.


Thus read-only transactions behave more like serializable isolation level than the default read committed.

Personally I use PostgreSQL 7.4 (which also uses MVCC instead of read locks), but the postgresql manual doesn't really explain how a READ ONLY transaction differs from a read-write, but I assume it's similar to Oracle.

However, all this still doesn't explain the difference between

Code:
SELECT blah blah


and

Code:
BEGIN
SELECT blah blah
COMMIT


i.e. running the query in a transaction, without specifying the transaction as read only. With read committed isolation level, I don't really see any difference between these two.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 30, 2004 4:59 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
you're right, i thought that transaction for a select query was unecessary, make a search on the forum and you'll see how gavin, christian, hibernate team, and baliukas.... react about this...., you'll find some detailled explanations

what i'm sure is that there is A difference between
Code:
select blahh
select bliiihhhh

and
Code:
Begin
select blahh
select bliiihhhhcommit
Commit


the first code do in fact:
Code:
Begin
select blahh
Commit
Begin
select bliiihhhhcommit
Commit


and you know that one of the things we love about hibernate is all lazy stuff.... which implies many select queries.

Again, excuse my english, we're learning many best practices from hibernate team and experienced users, i just wanted to advise that always using transaction is a kind of best practice.


Anthony


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 30, 2004 6:20 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
The first code snippet only behaves differently because auto commit mode is enabled. There is no communication with a database outside of a transaction, there is always a BEGIN and a COMMMIT, even if its only implicit by auto commit mode.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 31, 2004 4:42 am 
Regular
Regular

Joined: Wed Mar 03, 2004 9:38 am
Posts: 70
Ok, so I searched the forums, and as delpouve said, the hibernate team consistently recommends that also all read-only operations should be executed in a transaction.

A few related observations (assuming that in all cases autocommit is off, as it should be):

1. If the database supports read-only transactions, one might get a performance benefit from using them as committing a read-only transaction is a much simpler and thus slightly faster operation than committing or rollbacking a read-write transaction.

2. If one does read operations without a transaction, the database will implicitly start a new transaction. As this transaction is then never committed, there might be problems later on. E.g. starting a transaction after this will cause a warning that a transaction is already in progress, and the database will use the timestamp of the "non-transactional" read operation as the timestamp of the transaction.

3. About lazy loading in the view with the open session in view pattern. The first lazy load will start an implicit transaction, which is also used by subsequent lazy loads in the same request. However, I wouldn't worry that much about the transaction being left hanging, because when the view has been rendered the session is closed and the connection is returned to the pool. The connection pool should automatically execute a rollback on all returned connections, to ensure that all the connections are clean and in a consistent state.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 31, 2004 4:56 am 
Regular
Regular

Joined: Fri Nov 07, 2003 6:31 am
Posts: 104
Location: Beijing, China
joib wrote:
Take a look at the org.springframework.orm.hibernate.support.OpenSessionInViewFilter class. When using it the session is closed after the view has been rendered and thus lazy loading will work.

Note that using the open session in view pattern does change the transaction semantics of you application somewhat. My understanding is that lazy loads in the view will execute non-transactionally, so if that is a problem for you, you have to find some other approach (e.g. Hibernate.initialize() in your DAO methods). Personally, I don't think it's a big deal, since the lazy loads are read-only anyway.


I'm using OpenSessionInViewFilter, and any lazy loading is working in my apps (except some toString() that calls apache ToStringBuilder.reflectionToString which crashes lazy init. sometimes)
But when using BeanUtils.copyproperties(DTO, persistentObject) we end up with uninitialized part of the graph object referenced in the DTO.
When Velocity do a !$DTO.persistentObject.field1 it crashes.
I must admit this doesn't seems to always be the case.
So it probably should work.

As for transaction, I don't think there's any difference between lazy loads in view or in Action transaction wise.

But isn't it a bad practice to reference part of object graph in the DTO instead of copying only necessary data??


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 31, 2004 6:04 am 
Regular
Regular

Joined: Wed Mar 03, 2004 9:38 am
Posts: 70
nodje wrote:

I'm using OpenSessionInViewFilter, and any lazy loading is working in my apps (except some toString() that calls apache ToStringBuilder.reflectionToString which crashes lazy init. sometimes)


CGLIB is deep voodoo for me, but I suspect that using reflection on a proxy might very well lead to disaster. I also use the commons-lang builders, but I never use the reflection builders, I always specify which fields I want to use manually.

Quote:
But when using BeanUtils.copyproperties(DTO, persistentObject) we end up with uninitialized part of the graph object referenced in the DTO.
When Velocity do a !$DTO.persistentObject.field1 it crashes.
I must admit this doesn't seems to always be the case.
So it probably should work.


Shouldn't you do BeanUtils.copyproperties(DTO.getPersistentObject(), persistentObject) instead, if you attach the persistent object as a property in the DTO?

Quote:
As for transaction, I don't think there's any difference between lazy loads in view or in Action transaction wise.


In principle no. But the danger is that in an Action you can start another transaction after you have lazy loaded something outside a hibernate transaction, leading to problems explained in point #2 in my above post. When lazy loading in the view, you can be sure that it will be the last database access before the connection is returned to the pool and any non-finished transaction (such as the lazy load) rollbacked.

Quote:
But isn't it a bad practice to reference part of object graph in the DTO instead of copying only necessary data??


Well, doesn't that sort of defeat the purpose of using a DTO in the first place?


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.