-->
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.  [ 2 posts ] 
Author Message
 Post subject: Is this the correct way?
PostPosted: Tue May 06, 2008 5:08 am 
Newbie

Joined: Wed May 24, 2006 5:47 pm
Posts: 14
Hi all.
I have this scenario:

    Hibernate 3.2.6
    JVM 1.5_06
    Spring 2.5.1
    Apache tomcat 5.5.16
    MySql 5.0.18


I have to do an update of an entity mapped by Hibernate.
Image this java-bean that maps a database table:

Code:
public class User {
   
   private String name;
   private String surname;
   private String noInForm;
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getSurname() {
      return surname;
   }
   public void setSurname(String surname) {
      this.surname = surname;
   }
   public String getNoInForm() {
      return noInForm;
   }
   public void setNoInForm(String noInForm) {
      this.noInForm = noInForm;
   }
}


Now image that in my web form i have the possibility to mofiy only the name and surname and not the field notInform (this field is not mapped by a spring command); image i have a record in my DB with name, surname and noInForm with some datas.
I want to update this record by setting the new name and the new surname and leaving the old noInForm value; if i use the session.saveOrUpdate method by passing the user bean with the new values i have seen that the noInForm field is updated by a null value. I have to do a load of the entity and then set the new value in the loaded entity and then i have to saveOrUpdate the loaded entity.
I'ld love to avoid a select before the update; how can i do? Is there any method that can avoid me to do the select?

Sorry for my English..it's not great.

Thanks to all.
Regards,
Angelo.


Top
 Profile  
 
 Post subject: suggestions
PostPosted: Tue May 06, 2008 5:58 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
Hi,
I've asked myself the same questions a while ago in a recent project. Basically, there are 2 ways to go:

1. Use DTOs (Data Transfer Objects), i.e. if your entity should only be updated using a subset of its fields, create some MyEntityDTO class (or several DTO classes for a single entity, each used in a different situation), containing only the needed fields, and ensure your interfaces receive arguments of type MyEntityDTO instead of MyEntity.

This is a very common approach, and is usually chosen for several reasons:
a. large entities waste a lot of network bandwidth, so why pass unnecessary fields back for forth?
b. some roles are not allowed to see all fields of a certain entity, so you have the option of letting different roles run different methods, each passing/receiving a different DTO class.
c. The DTO class is known at runtime, giving developers who write clients a compile-time type checking of what they pass and what they are getting to/from your EJBs.

The downside of this, is that as your entities grow more and more complex, i.e. have derived classes, contain other entities which also have various implementations, etc, then your business interface becomes harder to maintain. In the worst case, if each method has its own DTO, you end up with (methods X entities) DTO class imlementations.
Another problem is complex entities: how do you define a DTO for an entity which contains other entities? Do you also define DTO's for them? What if those entities have derived classes? How do you "map" DTOs to entities?

Bottom line: If you choose this approach, you should try to estimate the level of complexity and expect a lot of DTO-entity mapping code when passing entity data to/from your business interface. You may even consider writing such a mapper module.


2. Do not use DTOs - pass entities as-is, only specify which properties you wish to update. For example, a business method may look like this:

Code:
setEntity(Entity e, Set<String> propertyNames) {
   Entity original = em.find(Entity.class, e.getId());
   helper.merge(original, e, propertyNames); // this copies only the relevant properties from 'e' to 'original'.
   em.merge(original);
}


Same idea may apply for getEntity(Long id, Set<String> propertyNames) and so on.

For my recent project, I chose this approach, because I estimated that the overall effort is smaller, even for complex entities. I was able to extend the mentioned 'helper' to satisfy most of my needs, so a single 'helper.merge' method covered 99% of my entities. It's also good for security, as I won't pass unneeded info over the wire and into the client. It's also a good compromise for network bandwidth: unneeded fields pass as null, which only lightly impacts bandwidth. However, there is a downside as usual:
a. Client developers don't have compile-time type checking and can only rely on documentation and runtime (i.e. exceptions, debugger) to know which fields are "valid" to pass to/from a certain business method. You should keep documentation and exception handling in sync, to avoid mis-written clients.
b. I had a hard time getting this to work with other EntityManager impls, such as TopLink. Hibernate worked fine with some effort. Specifically, watch out when you return an entity from your EJB to the client, which has lazy props...

good luck


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