-->
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.  [ 3 posts ] 
Author Message
 Post subject: Prevent duplicate rows when saving transient objects
PostPosted: Mon Jan 30, 2006 1:42 pm 
Newbie

Joined: Wed Jan 25, 2006 11:45 am
Posts: 4
Hi,

I need help preventing the creation of duplicate rows, caused by saving new transient objects.

The model I'm using consists of a user class and an authority class, which are both mapped to their respective tables, in a unidirectional many-to-one relationship.

ie. The user table has a foreign key, mapping the user to one of the available authorities. To keep this simple, I'll consider the case where the authority table contains only two columns, id and authority (varchar)

Now lets say there exists entries in the authority table such as....


id | authority
1 ADMIN
2 TESTER


Later on I may like to create a user, and attach an authority to it.

User admin = new User();
Authority auth = new Authority("ADMIN");
admin.setAuthority(auth);
userDao.insertUser(admin);


// UserDao
public void insertUser(User user) {
Session session = getSession();
session.saveOrUpdate(user);
session.flush();
}

I'm using cascading so that when the user is updated, it also maps the relation to its authority property. Now the problem is that since the Authority was a transient object, hibernate inserts a new row into the database. Which is NOT what I want.



id | authority
1 ADMIN
2 TESTER
3 TESTER


which consequently sets authority_id(fk) to 3 for our new users authority level.


So how can I prevent the duplication from occuring? There has to be a way to inform hibernate to ignore inserts if the entry exists. Although I of course would want hibernate to map the existing authority entry to my new user, as set users authority_id(fk) to 2.


The only solution I can come up with is to replace the "new Authority()" instantiation with a hibernate query that will return an existing authority.

This seems a bit awkward though, and would be rather unwiedly if there were other objects persisted in the same fashion.



Thanks for your time, sorry this got a bit long. If you require any more information please ask.




Hibernate version: 3.1
Name and version of the database you are using: MySQL 5.0


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 30, 2006 1:46 pm 
Senior
Senior

Joined: Tue Aug 23, 2005 8:52 am
Posts: 181
You need to define "equals" and "hashcode" in your Authority class. Refer to
http://www.hibernate.org/hib_docs/v3/re ... lshashcode
for the details.
Basically you need to use a column thats a business key(name in your case) and check for equality based on that.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 30, 2006 2:20 pm 
Newbie

Joined: Wed Jan 25, 2006 11:45 am
Posts: 4
Thanks for the quick reply rajasaur.

I had looked into that before, but it doesn't seem to help in my case. I believe that is because the object I'm referring to already exists in a database.

To use the .equals() or .hash(), hibernate would have to load in the entire Authority table, and for each of its rows, compare against my new insertion.

Maybe I'm missing something however, so let me include my annotated POJOs I use in my example.


Code:
@Entity
@Table(name = "users")
public class User
{
   private long      id;
   private Authority authority;

   private Date      registered;
   private String    username;
   private String    password;
   private String    firstName;
   private String    lastName;
   private String    email;
   private String    phoneNumber;
   private String    address;
   private String    city;
   private String    state;
   private String    postalCode;
   private String    country;


   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   public long getId() {
      return id;
   }

   public void setId(long id) {
      this.id = id;
   }

   @ManyToOne(cascade = CascadeType.ALL)
   public Authority getAuthority() {
      return authority;
   }

   public void setAuthority(Authority authority) {
      this.authority = authority;
   }

   @Temporal(TemporalType.TIMESTAMP)
   public Date getRegistered() {
      return registered;
   }

   public void setRegistered(Date registered) {
      this.registered = registered;
   }

   public String getUsername() {
      return username;
   }

   public void setUsername(String username) {
      this.username = username;
   }

         // for brevity I'm omitting the rest of the getters and setters...
}


Code:
@Entity
@Table(name = "authority")
public class Authority implements Serializable
{
   private long   id;
   private String role;


   public Authority() {

   }

   public Authority(String role) {
      this.role = role;
   }

   public boolean equals(Object obj) {
      if (this == obj) return true;
      if (! (obj instanceof Authority)) return false;
      final Authority other = (Authority) obj;
      return role.equals(other.getRole());
   }

   public int hashCode() {
      return role.hashCode();
   }

   public String toString() {
      return role;
   }

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   public long getId() {
      return id;
   }

   public void setId(long id) {
      this.id = id;
   }

   @Column(name = "role")
   public String getRole() {
      return role;
   }

   public void setRole(String role) {
      this.role = role;
   }
}


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