-->
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: Class hierarchy, one table per class, discriminator formula?
PostPosted: Sun May 01, 2011 7:03 pm 
Newbie

Joined: Fri Apr 29, 2011 5:30 pm
Posts: 5
I have this table in a legacy database:

Code:
ID   TYPE   NAME   ID_PARENT   TYPE_PARENT


It's very similar to the Category that appears in the book "Java persistence with hibernate", however, it has only two levels:

It has a composite key using the columns ID and TYPE. The ones named _PARENT have a relationship with the previous ones in this way:

- If ID and TYPE are equals to ID_PARENT and TYPE_PARENT, it means that we have a "parent category" (because its father is itself)
- If they're different, we have a "child category" (because its father is the one whose ID and TYPE are stored in ID_PARNT and TYPE_PARENT)

Is it possible to create some kind of formula to modelize something like this?

Code:
@Entity
@Table("CATEGORY")
@¿DiscriminatorFormula?
public abstract Category {
}

@Entity
@¿DiscriminatorFormula("ID=ID_PARENT AND TYPE=TYPE_PARENT")?
public CategoryParent extends Category {
}

@Entity
@¿DiscriminatorFormula("ID<>ID_PARENT AND TYPE<>TYPE_PARENT")?
public CategoryChild extends Category {
}


Thanks in advance


Top
 Profile  
 
 Post subject: Re: Class hierarchy, one table per class, discriminator formula?
PostPosted: Fri May 27, 2011 3:59 am 
Newbie

Joined: Fri Apr 29, 2011 5:30 pm
Posts: 5
Solved. At least the technical problem exposed.

You can find the solution in the very book "Java persistence with hibernate", maybe the actual problem is that I have a low level in reading comprehension (or the book is too dense, even though fantastic)

At the end of the 202 page you can read: "Sometimes, especially in legacy schemas, you don’t have the freedom to include
an extra discriminator column in your entity tables. In this case, you can apply a formula to calculate a discriminator value for each row:"

That is the solution: a DiscriminatorFormula using a SQL CASE/WHEN that results in literals that will be used as DiscriminatorValues in the child classes.

Code:
//Page 203: Formulas for discrimination aren’t part of the JPA specification. However, you can apply a Hibernate annotation
@Entity
@Table("CATEGORY")
@org.hibernate.annotations.DiscriminatorFormula("case when id=id_parent and type=type_parent then 'P' else 'C' end")
public abstract Category {
}

@Entity
@DiscriminatorValue("P")
public CategoryParent extends Category {
}

@Entity
@DiscriminatorValue("C")
public CategoryChild extends Category {
}


NOTE: I made an additional mistake in the previous code, the org.hibernate.annotations.DiscriminatorFormula "must be placed at the root entity" (as the API said).

Something similar applies to DiscriminatorValue: "this annotation can only be specified on a concrete entity class" (as the API said).


Top
 Profile  
 
 Post subject: Re: Class hierarchy, one table per class, discriminator formula?
PostPosted: Fri May 27, 2011 4:25 am 
Newbie

Joined: Fri Apr 29, 2011 5:30 pm
Posts: 5
Another problem remains, but it is a data problem.

As it had been done in the book, there is a relationship between categories:
Code:
@ManyToOne
private Category parentCategory;
...
@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE} mappedBy = "parentCategory")
private Set<Category> childCategories = new HashSet<Category>();


However, there is a chance to manipulate the database manually, and according to my first example, someone can insert a Child category whose related category isn't a Parent Category (according to the discriminator formula)

At this moment Hibernate cannot instantiate an appropriate object and the program simply crashes.

The actual problem is that in the error log is difficult to see that the there is a data problem.

Is it possible to catch the creation of the object before it's created in order to ensure that there won't be any problem?

Actually, I don't want to create a different kind of object, I only want to create a good warning containing the row that is creating the problem.

I tried with an Interceptor (extends EmptyInterceptor) executing a Query (entityManager.createNativeQuery) in the public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) method before returning super.onLoad(entity, id, state, propertyNames, types);.

But it failed (and the transaction is rollbacked)

Can anyone help me with this?


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.