-->
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.  [ 7 posts ] 
Author Message
 Post subject: Hibernate deletes all rows and then inserts them all again!
PostPosted: Fri Sep 05, 2008 8:05 am 
Newbie

Joined: Wed Sep 03, 2008 8:54 am
Posts: 4
Ok,

So what on earth is Hibernate up too? I have an entity like this:

<Car>
make
color
@OneToMany
List<Drivers> drivers


When I add a new driver to the Car entity and commit the changes Hibernate deletes all rows in the join table for that car and then inserts all the rows again plus the new one.

I can give specific code if anyone wants to see, but I get the feeling that this is something I'm inheriently doing wrong. I thought at first I must be inserting a new (replacing) List<Drivers> into Car, but I'm not.

Any ideas or points?
Thanks
Will


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 06, 2008 8:30 am 
Newbie

Joined: Wed Sep 03, 2008 8:54 am
Posts: 4
I really don't understand why this is happening. I must have missed some fundamental concept of Hibernate, but I just don;t see it.
Here's the code:

Code:
@Entity
public class Car {
   long id;
   private String make;
   private String color;
   private List<Driver> drivers = new ArrayList<Driver>();
   public String getMake() {
      return make;
   }
   public void setMake(String make) {
      this.make = make;
   }
   public String getColor() {
      return color;
   }
   public void setColor(String color) {
      this.color = color;
   }
   
   @OneToMany
   public List<Driver> getDrivers() {
      return drivers;
   }
   public void setDrivers(List<Driver> drivers) {
      this.drivers = drivers;
   }
   
   @Id
   @GeneratedValue
   public long getId() {
      return id;
   }
   public void setId(long id) {
      this.id = id;
   }
}

@Entity
public class Driver {
   long id;
   String name;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   @Id
   @GeneratedValue
   public long getId() {
      return id;
   }

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

}




If I have already inserted a car and driver then run this:
Code:
      HibernateUtil.begineTransaction();
      Car car = (Car)HibernateUtil.getSession().load(Car.class, new Long(1));
      
      Driver driver = new Driver();
      HibernateUtil.getSession().saveOrUpdate(driver);
      driver.setName("Bob");
      car.getDrivers().add(driver);
      
      
      HibernateUtil.commitTransaction();



My log says:
INFO - Version - Hibernate Annotations 3.3.0.GA
INFO - Environment - Hibernate 3.2.4.sp1
Hibernate: insert into Driver (car_id, name) values (?, ?)
DEBUG - LongType - binding null to parameter: 1
DEBUG - StringType - binding null to parameter: 2
Hibernate: select car0_.id as id7_0_, car0_.color as color7_0_, car0_.make as make7_0_ from Car car0_ where car0_.id=?
DEBUG - LongType - binding '1' to parameter: 1
DEBUG - StringType - returning 'blue' as column: color7_0_
DEBUG - StringType - returning 'audi' as column: make7_0_
Hibernate: select drivers0_.Car_id as Car1_2_, drivers0_.drivers_id as drivers2_2_, driver1_.id as id8_0_, driver1_.car_id as car3_8_0_, driver1_.name as name8_0_, car2_.id as id7_1_, car2_.color as color7_1_, car2_.make as make7_1_ from Car_Driver drivers0_ left outer join Driver driver1_ on drivers0_.drivers_id=driver1_.id left outer join Car car2_ on driver1_.car_id=car2_.id where drivers0_.Car_id=?
DEBUG - LongType - binding '1' to parameter: 1
DEBUG - LongType - returning '1' as column: id8_0_
DEBUG - LongType - returning null as column: id7_1_
DEBUG - LongType - returning null as column: car3_8_0_
DEBUG - StringType - returning 'JILL' as column: name8_0_
DEBUG - LongType - returning '1' as column: Car1_2_
DEBUG - LongType - returning '1' as column: drivers2_2_
Hibernate: update Driver set car_id=?, name=? where id=?
DEBUG - LongType - binding '1' to parameter: 1
DEBUG - StringType - binding 'Bob' to parameter: 2
DEBUG - LongType - binding '2' to parameter: 3
Hibernate: delete from Car_Driver where Car_id=?
DEBUG - LongType - binding '1' to parameter: 1
Hibernate: insert into Car_Driver (Car_id, drivers_id) values (?, ?)
DEBUG - LongType - binding '1' to parameter: 1
DEBUG - LongType - binding '1' to parameter: 2
Hibernate: insert into Car_Driver (Car_id, drivers_id) values (?, ?)
DEBUG - LongType - binding '1' to parameter: 1
DEBUG - LongType - binding '2' to parameter: 2

You can see that its deleting the join table and inserting all the elements again.
Please anyone can tell me what I'm doing wrong?
thanks[/b]


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 08, 2008 8:25 am 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
The behaviour of OneToMany mappings using List is "bag sematics" (see annotations docs). Hibernate's handling of these relationships is somewhat brute force i.e. it deletes existing entries and re-inserts to match the current collection.

Try using a Set or add a @CollectionId to create an idbag. There's some discussion in the annotations docs.

Or, instead of a join table (default behaviour) you could try a foreign column in the child table:
@OneToMany
@JoinColumn(name="car_id")


This article on performance comparison of bag vs idbag might also be useful:
http://swik.net/Hibernate/Hibernate+BAG+vs+IDBAG+Performance+Comparison


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2008 10:33 am 
Newbie

Joined: Tue Sep 16, 2008 10:32 am
Posts: 2
I had similar problems until I implemented equals() and hashcode() on my pojos. Might try that.

_________________
Andrew Morovati
Entrinsik Inc


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 17, 2008 5:03 am 
Newbie

Joined: Wed Sep 03, 2008 8:54 am
Posts: 4
Hi,

this seems just crazy - no (real) support for List.

I've just tried using a List in a ManyToMany situation as well, and I get the same results unless I use the CollectionId.

So basically I cannot us List with Hibernate without it deleting all rows in the join table? I must use Sets everywhere for OneToMany if I want uni-directional?

I tried the equals and hashcode methods as well, it didn't make any difference.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 18, 2008 12:35 pm 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
There *is* real support for lists using the IndexColumn annotation. Remember lists are ordered in java so to truely represent them in the database you need a column indicating the ordering.

I don't understand why its seemingly so important for you to use List when you don't care about the ordering. Especially when a Set is so easily converted to a List!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 23, 2008 2:38 am 
Newbie

Joined: Wed Sep 03, 2008 8:54 am
Posts: 4
thatmikewilliams wrote:
There *is* real support for lists using the IndexColumn annotation. Remember lists are ordered in java so to truely represent them in the database you need a column indicating the ordering.

I don't understand why its seemingly so important for you to use List when you don't care about the ordering. Especially when a Set is so easily converted to a List!


Hi,
yeah fair comments - I suppose I'm just surprised being a newbie with Hibernate. Its ok really, I just finding Hibernate has many more gotcha's than I thought, and documentation (for annotations) is very thin on the ground.


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