tags:

views:

330

answers:

1

Hello all, I have banged my self with a very particular problem. Using OpenJPA (KODO 4.1) is there a way to use more than one column as a discriminator column?

My problem is that i have a table structure (which i have limited ability to modify of course) similar to this:

Table  VEHICLE      EXPENSIVE_CAR  CHEAP_CAR       EXPENSIVE_BOAT    CHEAP_BOAT
---------------------------------------------------------------------------------
       HORSE_POWER  LUXURY_ACC     CLASIFICATION   SIZE              SIZE
       MEDIUM       EXTRAS                         TV_SIZE
       IS_EXPENSIVE CLASIFICATION

Where medium would discriminate between boat and car and is expensive would discriminate bettwen expensive or cheap.

So, is there any way to achieve this with the inheritance capabilities provided by OpenJPA (i know hibernate can use discriminator formulas but i am trying not to switch from the default JPA provider).

As a bonus if you can tell me about the custom discriminator strategies from OpenJPA that would be great since i have a hunch that it could be a plausible solution (even though i would prefer a vendor independent one)

Thanks a lot

A: 

Let's start backwards.

Discriminator strategies define the type of the column that discriminates related entities in the hierarchy. In JPA 1.x, it can be either a string (this is the default), a char and an integer. Example:

import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING, length = 5)
@DiscriminatorValue("FOO")
public class Foo { ... }

@Entity
@DiscriminatorValue("BAR")
public class Bar extends Foo { ... }

@Entity
@DiscriminatorValue("BAZ")   
public class Baz extends Baz { ... }

If you are using is single table inheritance strategy as the default, this setup means that all these entities that are in the hierarchy will be mapped to the database table of the parent class, meaning you'll have a FOO table in your db with all the attributes of classes Foo, Bar and Baz plus a discriminator column called TYPE with the type of string (most likely some varchar-variant, length 5) and for each entity type, the respective discriminator value will be inserted automatically when persisted.

When you are finding Bar or Baz entities with JPQL, JPA will be able to find the entities from the FOO table (because that is the parent entity's table), and by relying on the contents of the discriminator column, your JPA provider will be able to discriminate between creating some Bar or Baz entities.

If you'd set the discriminator type to INTEGER or CHAR, then you could write for the values 1, 2, 3 or "A", "B", "C" etc. respectively.

Now to the OpenJPA question.

AFAIK there's no way to easily specify multiple discriminator values with OpenJPA, but you can create some more complex entity hierarchies, so if you'd be able to modify the schema, you could create a Vehicle entity, a Car, a Boat and both an ExpensiveBoat and an ExpensiveCar.

If you have to stick with your schema, I guess (but FIXME) you are using the joined or the table per class inheritance strategy which means you cannot use the discriminator feature that JPA provides.

Tamás Mezei
It is not mandatory to use joined or table_per_class strategy when you do not have access to the schema but often that is the only strategies that make sense IRL.
Monachus
Indeed, you are right.
Tamás Mezei