-->
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.  [ 6 posts ] 
Author Message
 Post subject: Using Hibernate to read DTOs directly
PostPosted: Fri Aug 20, 2004 10:56 am 
Newbie

Joined: Fri Aug 20, 2004 10:07 am
Posts: 9
Location: Sweden
I am evaluating Hibernate to see if we can use it instead of our current ORM tool. One feature we use today that I haven't so far been able to get to work in Hibernate is to read DTOs directly from the database instead of reading entities and then copying data to the DTOs.
I know there has been a lot of discussion on whether to use DTOs or not but skipping the DTOs is not an option for me for legacy reasons.
The DTOs are similar to the entity classes but lack some properties which are only kept in the domain layer.

Example:
There is an entity Car which has a one-to-many association to entity Seat.
These are mapped to one table each, eg Car_Tb and Seat_Tb respectively.

Besides the classes Car and Seat which only exist in the domain layer I need two DTOs: CarTO and SeatTO.
CarTO and SeatTO are mapped to the same tables as Car and Seat, but only the properties needed in the DTOs are mapped.

When loading a DTO I immediately evict it to avoid any flushing:

Code between sessionFactory.openSession() and session.close():

Code:
      Session session = sessionFactory.openSession();
      CarTO dto = (CarTO) session.get(CarTO.class, id);
      session.evict(dto);
      session.close();
      return dto;


This works fine besides the collections. The DTOs use Hibernates own collection implementations which make the DTOs unusable in layers that don't know about Hibernate, such as desktop clients.

I have tried to use a PropertyAccessor to replace the collection implementations with the ones from java.util, ie HashSet and ArrayList, but then the evict will not work properly as it seems to rely on Hibernates collection implementations.

What I need is a Session.get() method that automatically evicts the entities and therefore don't need to use special collection implementations.

Any hints on how this can be done?

Peter

Hibernate version: 2.1.4
Mapping documents:

<class name="Car" table="Car_Tb">
<id name="Id" column="CAR_ID" type="int">
<generator class="assigned" />
</id>
<version name="UpdateId" column="Update_Id" type="long" />
<property name="Name" type="string" />
<property name="Type" type="long" column="Type" />
<property name="CreatedWhen" type="timestamp" column="Created_When"/>
<property name="CreatedBy" type="long" column="Created_By" />
<property name="UpdatedBy" type="long" column="Updated_By" />
<property name="UpdatedWhen" type="timestamp" column="Updated_When" />
<set name="Seats" cascade="all-delete-orphan" >
<key column="CAR_FK" />
<one-to-many class="Seat" />
</set>
</class>

<class name="Seat" table="Seat_Tb">
<id name="Id" column="SEA_ID" type="int">
<generator class="assigned" />
</id>
<version name="UpdateId" column="Update_Id" type="long" />
<property name="Color" type="string" />
<property name="Size" type="string" />
<property name="CreatedBy" type="long" column="Created_By" />
<property name="CreatedWhen" type="timestamp" column="Created_When"/>
<property name="UpdatedBy" type="long" column="Updated_By" />
<property name="UpdatedWhen" type="timestamp" column="Updated_When" />
</class>

<class name="CarTO" table="Car_Tb">
<id name="Id" column="CAR_ID" type="int">
<generator class="assigned" />
</id>
<version name="UpdateId" column="Update_Id" type="long" />
<property name="Name" type="string" />
<property name="Type" type="long" column="Type" />
<set name="Seats" cascade="all-delete-orphan">
<key column="CAR_FK" />
<one-to-many class="SeatTO" />
</set>
</class>

<class name="SeatTO" table="Seat_Tb">
<id name="Id" column="SEA_ID" type="int">
<generator class="assigned" />
</id>
<version name="UpdateId" column="Update_Id" type="long" />
<property name="Color" type="string" />
<property name="Size" type="string" />
</class>


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 20, 2004 10:59 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
take a look at projection i.e. "select new DTO(myObj.prop1,myObj.prop2) from Object myObj"

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 20, 2004 11:43 am 
Regular
Regular

Joined: Wed Aug 18, 2004 5:16 am
Posts: 69
Location: Modena, Italy
Hi Anthony,
is also possible to use collections in the constructor of the DTO?

I have used a HQL
Code:
"select new DataModuleInfo(dm.dmc, dm.type, elements(dm.items)) from DataModuleInfo dm"

where dmc is String, type is char and items is a Set but Hibernate send a
Code:
net.sf.hibernate.PropertyNotFoundException: no appropriate constructor in class: com.caliari.nova.ietm.DataModuleInfo

What type of collection is passed to contructor?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 20, 2004 11:49 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
i've never tried this... i think you've tried the same type as returned by the query.

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 23, 2004 3:00 am 
Regular
Regular

Joined: Wed Aug 18, 2004 5:16 am
Posts: 69
Location: Modena, Italy
Yes, is the same type. It can be a problem?
I have defined 2 constructor, a default constructor and a constructor for the projection.

Someone can explain how to use collections in this type of projection?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 23, 2004 3:55 am 
Newbie

Joined: Fri Aug 20, 2004 10:07 am
Posts: 9
Location: Sweden
I'm thinking of using a separate read-only session for reading the DTOs and then using a property accessor for swithing collection implementations.
That way I can avoid the problem with evict requiring Hibernate collection implementations. A separate session is needed because I might modify some Hibernate entites in the same transaction and those I want to flush.

Do you see any problem with this approach?

Code:
      Session session = sessionFactory.openSession();
      session.setFlushMode(FlushMode.NEVER);
      CarTO dto = (CarTO) session.get(CarTO.class, id);
      // No evict needed
      session.close();
      return dto;


set-method in Setter returned by the PropertyAccessor:

Code:
    public void set(Object theTarget, Object theValue) throws HibernateException {
      // Switch collections
      Object value = theValue;
      if (theValue instanceof Set) {
        value = new HashSet((Set) theValue);
      }
      else if (theValue instanceof List) {
        value = new ArrayList((List) theValue);
      } else
        value = theValue;
           
      DTO to = (DTO) theTarget;
      // Generic set-method present in all our DTOs, could of course be replaced by reflection or cglib
      to.set(KEY, value);
    }


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.