-->
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.  [ 9 posts ] 
Author Message
 Post subject: Hibernate single table inheritance for many to one
PostPosted: Tue Mar 09, 2010 10:55 am 
Newbie

Joined: Tue Mar 09, 2010 10:26 am
Posts: 2
We have the following entities (names changed to protect the innocent).

Code:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Foo<T extends FooType> extends BaseEntity {

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "typeID", nullable = false)

   private T type;
   
}

@Entity
public class GoodFoo extends Foo<GoodFooType> {
}


@Entity
public class BadFoo extends Foo<BadFooType> {
}

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class FooType extends BaseEntity {

}


@Entity
@DiscriminatorValue("GoodFooType")
@ForceDiscriminator
public class GoodFooType extends FooType {

}


@Entity
@DiscriminatorValue("BadFooType")
@ForceDiscriminator
public class BadFooType extends FooType {

}



When I retrieve a GoodFoo I get back a GoodFoo with a related GoodFooType as expected. When I retrieve a BadFoo I get back a BadFoo with a GoodFooType (not expected) event though the DTYPE in the FooType table is "BadFooType". Any ideas?


Top
 Profile  
 
 Post subject: Re: Hibernate single table inheritance for many to one
PostPosted: Wed Mar 10, 2010 4:45 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Beside of your problem I must say that personally never would do this approach:
Fields DTYPE and type should contain conceptually the same information.
This goes against normalization as redundancy in the schema should be avoided.


Top
 Profile  
 
 Post subject: Re: Hibernate single table inheritance for many to one
PostPosted: Wed Mar 10, 2010 10:57 am 
Newbie

Joined: Tue Mar 09, 2010 10:26 am
Posts: 2
DTYPE is the hibernate discriminator column which has no relationship to my type object, which contains type'ish fields. You could substitute the object name of choice here, the issue remains.


Top
 Profile  
 
 Post subject: Re: Hibernate single table inheritance for many to one
PostPosted: Wed Mar 10, 2010 12:09 pm 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Quote:
the issue remains.


I did'nt state that I have a solution for you issue.
Even if DTYPE has no relationship to your type object, that what you excpect seems to be:

retrieve a GoodFoo: get back a GoodFoo with a related GoodFooType
retrieve a BadFoo: get back a BadFoo with a related BadFooType

So abstractly seen you intend to store the same information into type as into DTYPE (even if in completly different store format),
which means redundancy.
Please correct me, if I am wrong.


Top
 Profile  
 
 Post subject: Re: Hibernate single table inheritance for many to one
PostPosted: Wed Mar 10, 2010 6:05 pm 
Newbie

Joined: Tue Aug 12, 2008 12:59 pm
Posts: 6
Location: Massachusetts
I am going to attempt to clarify the issue we are having (I work with Nathan, who posted the issue).

The actual issue is that hibernate is showing the wrong subclass type when data is retrieved.

We are able to add the data correctly and if we look in the database it shows the correct type but when we query the table it shows all of the values with the same subclass type even though they are actually different.

The issue only appears to affect a subclass within a subclass.

Here is a scenario similar to what we are trying to do. I will use vehicles to make it easier to follow.

We have an abstract class of Vehicle that has subclasses (Truck, Car, Motorcycle).

We have an abstract class of VehicleType that has subclasses (TruckType, CarType, MotorcycleType).

Data in the VehicleType table:
ID Discriminator Description
1 CarType Chevrolet
2 CarType Buick
3 CarType Toyota
4 MotorcycleType Harley Davidson
5 MotorcycleType Honda
6 TruckType Mack
7 TruckType GMC

Data in the Vehicle table:
ID Discriminator Serial number VehicleType
101 Motorcycle 654321 4
102 Car 123457 3
103 Truck 321456 7
104 Motorcycle 654123 5
105 Car 123456 1

If we query the entire VehicleType table we get 7 rows and each row shows the class as being the correct subtype.

If we query the entire Vehicle table we get 5 rows and each vehicle shows as the correct subclass. The problem is that when you look at the type WITHIN each row they ALL show as subclass of CarType, even though they show the correct type ID (vehicle 101 has type 4, vehicle 102 has type 3, etc.).

We have tried this with both eager and lazy loading. With eager loading an error occurs when you run the query. With lazy loading the query runs fine but the error occurs when you attempt to access the vehicle type.

In both cases the error is an EntityNotFoundException. If we try to retrieve vehicle id 101 we get the exception with a message of "Unable to find xxx.xxx.Car with id of 4". If you look in the database vehicle 101 has a type ID of 4 and if you look at the vehicle type table id 4 is a type of motorcycle (which is correct). For some reason it appears that hibernate is always expecting the vehicle type to be a CarType subclass regardless of what the data in the table is.

Here is an example of what the class definitions would look like:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Vehicle<T extends VehicleType> extends BaseEntity {

@Column(nullable = false, columnDefinition = "INT(11) UNSIGNED")
private Integer id;

@Column(nullable = false, columnDefinition = "INT(11) UNSIGNED")
private Integer serialNumber;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "typeID", nullable = false)
private T vehicleType;
}

@Entity
public class Car extends Vehicle {
}

@Entity
public class Motorcycle extends Vehicle {
}

@Entity
public class Truck extends Vehicle {
}

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class VehicleType extends BaseEntity {

@Column(nullable = false, columnDefinition = "INT(11) UNSIGNED")
private Integer id;

@Column(nullable = false, columnDefinition = "INT(11) UNSIGNED")
private String description;
}

@Entity
public class CarType extends VehicleType {
}

@Entity
public class MotorcycleType extends VehicleType {
}

@Entity
public class TruckType extends VehicleType {
}

I hope this clarifies the issue we are having and that someone has a solution to this issue.


Top
 Profile  
 
 Post subject: Re: Hibernate single table inheritance for many to one
PostPosted: Thu Mar 11, 2010 3:30 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Thank you JHaberlin,

now the problem is well explained.

The main question IMHO is whether hibernate supports generalizations (with type parameter T ) in annotated entities
like you do here:
Code:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Vehicle<T extends VehicleType> extends BaseEntity


In theory Hibernate would have to instantiate each Vehicle twice when loading a record from db.
First Hibernate cannot know the value of parameter T and must guess to instantiate a new Vehicle object,
only after having read Vehicle.typeID=4 hibernate in theory could create a new Vehicle with correct parameter T (new Vehicle<MotorcycleType>) but I really assume that such mechanism is not provided in Hibernate.

Did you read somewhere that Hibernate supports generalizations (with type parameter T ) in annotated entities ?


Top
 Profile  
 
 Post subject: Re: Hibernate single table inheritance for many to one
PostPosted: Thu Mar 11, 2010 12:53 pm 
Newbie

Joined: Tue Aug 12, 2008 12:59 pm
Posts: 6
Location: Massachusetts
Thanks for the response, pb00067.

I didn't read that Hibernate supports generics, I was just unaware that it didn't.

I see your point with needing to instantiate the object twice. One thing I tried was changing the VehicleType superclass to be concrete (removed the "abstract" from the class definition) hoping that it would then be able to instantiate the superclass, regardless of which subclass it actually was.

This didn't work, but I found it interesting that when I removed the generics and defined the vehicleType within Vehicle as a type of VehicleType that it shows the type as VehicleType regardless of whether the actual value is a CarType, MotorcycleType or TruckType. I am not sure why Hibernate cannot do this when it is defined as a generic. (It even shows the type as being VehicleType when VehicleType is defined as abstract.)

As I mentioned, I removed the generics and it seems to work. I also override the setVehicleType method in each subclass and throw and IllegalArgumentException if the subclass of the VehicleType is not correct for the Vehicle subclass. Would you agree with this approach or do you have another suggestion?


Top
 Profile  
 
 Post subject: Re: Hibernate single table inheritance for many to one
PostPosted: Fri Mar 12, 2010 3:46 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
No other suggestion (never had to implement such scenario).


Top
 Profile  
 
 Post subject: Re: Hibernate single table inheritance for many to one
PostPosted: Thu Sep 16, 2010 4:58 am 
Newbie

Joined: Wed Sep 15, 2010 7:15 am
Posts: 2
As many others I'm also suffering with the lack of support for generic relationships in Hibernate. See here.

Does anyone from Hibernate team know if this feature is already requested? Otherwise I can open a JIRA issue for this.


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