-->
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: Best practice on how to delete object references
PostPosted: Fri Oct 17, 2008 9:35 am 
Newbie

Joined: Fri Sep 26, 2008 10:48 am
Posts: 10
Hello!

I have a general question on how to delete object references.

Let's say I have two objects named Vehicle and Color. I have a unidirectional many-to-one relation from Vehicle to Color.

If I delete a Color object I understand that I have to set all references to this object to null. I'm a bit stuck with finding the best solution. I have three possibilities:

1) Check every Vehicle object for a matching Color reference and set to null
2) Make the relationship bidirectional, get Color object and do a vehicles.clear()
3) Enable "on delete set null" in the database for the relation

To me the second solution seems to be the best one. Can someone please give me some advice on that?

Thanks,

Fabian


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 17, 2008 12:59 pm 
Expert
Expert

Joined: Mon Nov 26, 2007 2:29 pm
Posts: 443
Fabian,

First, you have to decide if, in your business model, it makes sense that a vehicle have no color., which will determine whether the foreign key is nullable or not in your DB.

Then, you have to check if "color" is something that applies to other entities as well. Are there things other than vehicles that have color?
If not, then Color is not an entity like Vehicle, but rather a "value type".

This is an important distinction, because if color is a value type, then it is copied "by value" on every vehicle, hence, if you delete Color.Red from a given vehicle, the rest of the red vehicles still keep their own copy
Color.Red.

Make sure you understand this before going on.

Now, if Color were an entity instead of a "value type". that means that if a color red is deleted, it is deleted for all other entities that share references to it.
A shared reference is just that, a reference. So you don't have to go around all objects in your model and check who is red. You just delete Color.red and that's it.

Your questions hint me that you are not clear on the difference between an entity and a "value type", and/or that you have not quite decided what the best type of association between vehicle and color is the best.

Sepcifically:

- option 1) only would apply if Color were a "value type", not an entity.
- option 2) assumes that color is an entity, not a "value type". In that case, you don't need to notify your vehicles of the deletion of that color, and don't have to be afraid of causing foreign key violations
- option 3) is not advised, you should sole this persistence issue through Hibernate, not forcing the database to do thing of which Hibernate might be unaware.

_________________
Gonzalo Díaz


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 17, 2008 3:36 pm 
Newbie

Joined: Fri Sep 26, 2008 10:48 am
Posts: 10
Hello Gonzalo,

thanks for your reply.

In fact, Color should be an entity because there will be several pre-defined colors one can choose from when creating a vehicle. As far as I understood value-types, it is not possible to have a list of pre-defined colors if there are no vehicles referencing them.

Maybe I should be a bit more specific on the relation between Vehicle and Color: The relationship I created in Hibernate is a unidirectional relation from Vehicle -> Color. For me, this results in a vehice having a Color-typed field. Hibernate generates a foreign key constraint for this. (Maybe this is where I made a mistake?) As soon as I try to delete a Color, I get a constraint violation. Taking into account your explanation, I think this means that the Color-typed field in Vehicle is not nullable, right?
So the solution to my problem would be to set the reference nullable.

Maybe there is a second problem: I always try to store lists (like colors) one can choose from in the database. I never thought about this being wrong. Do you know of any problems or can you recommend something better?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 17, 2008 4:15 pm 
Expert
Expert

Joined: Mon Nov 26, 2007 2:29 pm
Posts: 443
Yes, your constraint violation is probably due to a non-nullability constraint, not due the foreign key constraint.
What does the DB error say, exactly?

_________________
Gonzalo Díaz


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 21, 2008 3:49 am 
Newbie

Joined: Fri Sep 26, 2008 10:48 am
Posts: 10
I get a ConstrainViolationException. It's in german, I hope the translation is accurate:

Quote:
Update or delete on table "color" violates foreign key constraint "1234" on table "vehicle". The key is still referenced from table "vehicle"


Unfortunately the problem is still present. The only thing I can do to get around it is to alter the foreig key constraint and add the option "ON DELETE SET NULL" which is "ON DELETE NO ACTION" by default.

Here is my code:

Vehicle.java

Code:
@Entity
@SequenceGenerator(name="vehicle_seq",sequenceName="vehicle_id_seq")
public class Vehicle{
   
   private int id;
   private String name;
   
   private Color color;
   
   @Id  @GeneratedValue(generator="vehicle_seq",strategy=GenerationType.SEQUENCE)
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   
   @ManyToOne
   @JoinColumn(nullable=true)
   public Color getColor() {
      return color;
   }
   public void setColor(Color color) {
      this.color = color;
   }

}




Color.java:

Code:

@Entity
@SequenceGenerator(name="color_seq",sequenceName="color_id_seq")
public class Color {

   
   public int id;
   public String name;
   
   @Id @GeneratedValue(generator="color_seq",strategy=GenerationType.SEQUENCE)
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   
}




I'm using a PostgreSQL database. The tables generated by hbm2ddl look as follows:


Vehicle table:

Code:
CREATE TABLE vehicle
(
  id integer NOT NULL,
  name character varying(255),
  color_id integer,
  CONSTRAINT vehicle_pkey PRIMARY KEY (id),
  CONSTRAINT fk27fbe3feda3c3806 FOREIGN KEY (color_id)
      REFERENCES color (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITHOUT OIDS;
ALTER TABLE vehicle OWNER TO dankof;


Color table:


Code:

CREATE TABLE color
(
  id integer NOT NULL,
  name character varying(255),
  CONSTRAINT color_pkey PRIMARY KEY (id)
)
WITHOUT OIDS;
ALTER TABLE color OWNER TO dankof;



Top
 Profile  
 
 Post subject: Use @JoinTable instead of @JoinColumn
PostPosted: Thu Feb 03, 2011 10:37 am 
Newbie

Joined: Mon Jan 31, 2011 3:23 pm
Posts: 5
Hi,
sorry for pulling up and old thread. But as I have stumped into the same problem and did not find an answer elsewhere, I thought it might help someone else.
Using @JoinTable does the trick. Your mapping will look as follows:

Code:
@ManyToOne
@JoinTable(name = "Color_of_Vehicle")
@OnDelete(action = CASCADE)
public Color getColor() {
  return color;
}



This will cause Hibernate to generate the join table and two FK-Constraints. The FK-Constraint referencing from Vehicle to color will have ON DELETE CASCADE. This way you can have Vehicles with color==null, you can delete Vehicles with Color != null and can only delete Color that is not used by a Vehicle.

Cheers nillehammer

_________________
http://www.winfonet.eu


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.