-->
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 3 mapping advice
PostPosted: Sat Apr 14, 2007 3:48 pm 
Newbie

Joined: Tue Apr 18, 2006 6:43 pm
Posts: 11
hello,

this may sound stupid but ...

i have to create a domain entity model for vehicles, makes and models.

a vehicle can be a car or a boat. also the make has a type because cars have different makes from boats (and i need to distinguish them when the user selects the make in a form). I was about to map an entity for the make but because they finite (cars, boats, motorcycles) perhaps the best is to use constants in a typesafe enum for example.

to map that in hibernate do i need a user type? or an simple int/Integer is fine? when i load a vehicle from the database i need to kno what type is it and by using the TypeSafe Enum u could just do

v.getType()==VehicleType.CAR

am i right ?

thank you


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 14, 2007 9:48 pm 
Senior
Senior

Joined: Tue Mar 09, 2004 2:38 pm
Posts: 141
Location: Lowell, MA USA
Hibernate works with Java 5 Enum types just fine. You just need to specify how the Enum is stored in the database (int or string) by adding the following annotation:
Code:
@Enumerated(EnumType.STRING) | @Enumerated(EnumType.INT)

However, what would be better is to use inheritance mapping. The enum solution would work, but it doesn't prevent a Boat from having tires or a car from being an AirBus Camry :) . With inheritance mapping, vehicles could share a base class, and different specialization's could use different properties. Such an object model could look like this:

Code:
Vehicle
Car
Boat
Plane


Your data model will dictate how what inheritance strategy you choose. But if you have flexibility on your how your data model looks, I'd suggest the joined sub-class strategy. The inheritance mapping strategy strategy can help you use Java's type-safety to enforce your business rules. Hope this helps.

Ryan-

_________________
Ryan J. McDonough
http://damnhandy.com

Please remember to rate!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Apr 15, 2007 12:34 am 
Newbie

Joined: Tue Apr 18, 2006 6:43 pm
Posts: 11
rephrasing:
i have finite types of vehicles. the Vehicle class has a Make class, no problem there as Vehicle as a FK to the make. For distinguishing wich available Makes apply to each vehicle, they also have a type. so the type is shared and of the same domain.

- i mapped the types in an enum (VehicleType)
- used @MappedSuperclass in BaseEntity
- @Inheritance(strategy = InheritanceType.JOINED) in Vehicle
- the Vehicle class is abstract and the contructor protected so the developer (me) has to call super in the descendant classes (Car), with an VehicleType value, defining the type
- both Car and Make have :
@Enumerated(EnumType.ORDINAL)
private VehicleType vehicleType;

BaseEntity
-> Vehicle
-> Car
-> MotorCycle

i think i used both the enum and the inheritance. my ingenious super mind (not) has come up with this:

Code:
pt.standout.db.core.domain.base.BaseEntity.java
------------------------------------------------------

package pt.standout.db.core.domain.base;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

/**
* @author josemoreira
* The mother of all entities
*
*/
@MappedSuperclass
public class BaseEntity implements Serializable {

   static final long serialVersionUID = 1L;

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id")
   private Long id;

   /**
    * @return
    */
   public Long getId() {
      return id;
   }

   /**
    * @param id
    */
   public void setId(Long id) {
      this.id = id;
   }
}


pt.standout.db.catalog.domain.Vehicle.java
------------------------------------------------------

package pt.standout.db.catalog.domain;

import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

import pt.standout.db.catalog.usertype.VehicleType;
import pt.standout.db.core.domain.base.BaseEntity;

/**
* @author josemoreira
*
*/
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Vehicle extends BaseEntity {

   /**
    *
    */
   private static final long serialVersionUID = 1L;

   @Enumerated(EnumType.ORDINAL)
   private VehicleType vehicleType;

   protected Vehicle(VehicleType vehicleType) {
      this.vehicleType = vehicleType;
   }

   public VehicleType getVehicleType() {
      return vehicleType;
   }
}

pt.standout.db.catalog.domain.Car.java
------------------------------------------------------

package pt.standout.db.catalog.domain;

import javax.persistence.Entity;
import javax.persistence.Table;

import pt.standout.db.catalog.usertype.VehicleType;


/**
* @author ethernal
*
*/
@Entity
@Table(name="catalog_car")
public class Car extends Vehicle {

   /**
    *
    */
   private static final long serialVersionUID = 1L;

   public Car() {
      super(VehicleType.CAR);
   }

}


pt.standout.db.catalog.usertype.VehicleType.java
------------------------------------------------------

/**
* The vehicle type (car, boat, motorcycle)
*/
package pt.standout.db.catalog.usertype;

import java.util.ArrayList;
import java.util.List;

/**
* @author josemoreira
*
*/

public enum VehicleType {

   CAR(1), BOAT(2), MOTORCYCLE(3);

   private int type;

   private static final List<VehicleType> types = new ArrayList<VehicleType>();

   static {
      for (VehicleType type : VehicleType.values())
         types.add(type);

   }

   public int value() {
      return type;
   }

   private VehicleType(int type) {
      this.type = type;
   }

}



what do you think?

The Vehicle should also have a Model property that i havent added yet.

also is there a way to enforce (or should i) that a vehicle cant have a Model for wich the types anrent the same, through annotations?


thank you \O/


Top
 Profile  
 
 Post subject:
PostPosted: Sun Apr 15, 2007 7:56 am 
Senior
Senior

Joined: Tue Mar 09, 2004 2:38 pm
Posts: 141
Location: Lowell, MA USA
This looks pretty good. I too use the combo enum-inheritence approach as well as sometimes you need some of that meta-data available in the super class.

To answer your question about Makes & Models, you could potentially do the same thing. Each Make could be a class and each Model could have a specialization such as CarModel, BoatModel, MotorcycleModel, etc. The vehicle could define an abstract getModel() method and the Car specialization could have setCarModel() method which only takes car models. The other reason why I'd suggest this is that model change from year to year and storing these values in a table would add some flexibility. Hope this helps.

Ryan-

_________________
Ryan J. McDonough
http://damnhandy.com

Please remember to rate!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 25, 2007 7:18 pm 
Newbie

Joined: Tue Apr 18, 2006 6:43 pm
Posts: 11
this aproach brings me some doubts....
imagine i have to retrieve a list of all vehicles ordered by price, being price a Vehicle property.

I could query for Vehicle i guess, but imagine that each row of the presented list has some Car/Boar/Motorcycle specific information. I need to cast to the specific object and that means to load the Car instance using its Vehicle ID, right? that sounds like N+1 queries.

How do i do that? get the result of Vehicles and for each one, depending of the type (if statement) load the specific object by ID and add to a second list?

pseudo-like:

result1 = dao.getVehiclesByPrice()

foreach result1 as vehicle
if vehicle.type=car
Car car = dao.getCar(vehicle.getId())
result2.add(car)
....

i hope i've explained myself :p


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 26, 2007 9:27 am 
Senior
Senior

Joined: Tue Mar 09, 2004 2:38 pm
Posts: 141
Location: Lowell, MA USA
Quote:
I could query for Vehicle i guess, but imagine that each row of the presented list has some Car/Boar/Motorcycle specific information. I need to cast to the specific object and that means to load the Car instance using its Vehicle ID, right? that sounds like N+1 queries.


It's not an N+1 query. In fact, Hibernate will executed 1 query to return a collection of Vehicles. Each instance in the collection will be of the specified type and casting will not trigger an additional query.

I have done this type of structure before for a trading system. There were 5 types of items that could be traded and there were all derived from a parent class. We also used the table-per-subclass strategy and querying on the superclass returned a collection of the superclass instance. When you inspect the collection, you'll see that it actually contained the specialization.

Hope this clarifies things.

Ryan-

_________________
Ryan J. McDonough
http://damnhandy.com

Please remember to rate!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 26, 2007 11:12 am 
Newbie

Joined: Tue Apr 18, 2006 6:43 pm
Posts: 11
yes :) a big dooh for me.


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.