Composite discriminator jpa - java

I'm getting extra DTYPE in my query while my jps entities are structured as follow:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="PRODUCT_TYPE")
public abstract class Product extends Tent implements Serializable {
##ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PRODUCT_TYPE")
private TransType transType;
...
}
#Entity
#Table(name="CAR")
#DiscriminatorColumn(name="CAR_TYPE")
public class Car extends Product {
#Column(name = "car_ent_id", insertable = false, updatable = false)
private int carEntId;
....
}
Tent
|
Product
|
LEVEL-1 -->[Car_1_1] [car_1_2]....
|
LEVEL-2 -->[car_2_1] [car_2_2]...
So what I'm trying to achieve, discriminate all the entities at both LEVEL-1 and 2 together. Abstract class Product is having type which discriminating immediately 1 level down but when we are further extending level 1 entities at level 2. This's where I'm not having any clue.
Can we have custom non-db field defined in Product and assigning a value to each level-1 entity and for level-2 entities TYPE can work somehow?
Not really having any clue
Thanks

Related

Mapping database lookups to jpa entities

I have the following database tables: lookup and employee.
Lookup Table: structure with sample data.
class_name value description
GENDER_CODE 1 Male
GENDER_CODE 2 Female
BANK_CODE 1 HSBC
BANK_CODE 2 CityBank
Employee Table: structure with sample data.
id name gender_code bank_code
1 Yusuf 1 1
2 Maher 1 2
3 Suzan 2 1
What is the best way to map them into JPA entities?
I tried to map an abstract class to lookup table and use class_name column as discriminator for the subclasses Gender and Bank and reference the bank and gender as ManyToOne in the employee object.. but I'm getting a class cast exception when the gender_code and bank_code has the same value.
I tried to create views gender_lookup and Bank_lookup and map them directly to entities. Again hibernate complains that he can't find a table with such name.
I would try to map the lookuptable as n+1 separated entities, one abstract and n childs.
Mapped superclass should have SINGLE_TABLE inheritance and child classes need to declare the discriminator.
Something like this:
#MappedSuperclass
#DiscriminatorColumn(name = "class_name")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class LookupTable{
#Id
private Long vale;
#Column(nullable = false)
private String description;
// Getters and setters
}
#Entity
#DiscriminatorValue("GENDER_CODE")
public class GenderCode extends LookupTable() {
}
#Entity
#DiscriminatorValue("BANK_CODE")
public class BankCode extends LookupTable() {
}
#Entity
public class Employee{
#Id
private Long id;
#Column(nullable = false)
private String name;
#Column(nullable = false)
private GenderCode genderCode;
#Column(nullable = false)
private BankCode bankCode;
}

Hibernate inheritance and polymorphism

I have a class hierarchy that i've mapped to a database with Hibernate using the single table per class hierarchy strategy.
Here is the UML of my class Hierarchy
class hierarchy UML diagram
The Hibernate mapping is as follows
#Entity
#Table(name = "FRUIT_HIERARCHY")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
public abstract class Fruit{
#Id
#Column(name = "id_registred_user")
private long id;
}
#DiscriminatorValue(value = "Banana")
public class Banana extends Fruit{}
#DiscriminatorValue(value = "Orange")
public class Orange extends Fruit{
#OneToMany(mappedBy = "orange", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Note> noteList;
}
Here is the details concerning my Postgresql database
database schema
Here is the database
create table FRUIT_HIERARCHY (
ID_FRUIT SERIAL not null,
DISCRIMINATOR VARCHAR(50) null,
constraint PK_FRUIT_HIERARCHY primary key (ID_FRUIT)
);
create table NOTE (
ID_NOTE SERIAL not null,
ID_FRUIT INT4 not null,
constraint PK_NOTE primary key (ID_NOTE)
);
alter table NOTE
add constraint FK_NOTE_FRUIT foreign key (ID_FRUIT)
references FRUIT_HIERARCHY (ID_FRUIT)
on delete restrict on update restrict;
The problem comes when i have to implement the hibernate association between Orange class and Note. An Orange has 0 to n Notes and a Note belong to one Orange. And Orange is a subclass of Fruit.
#Entity
#Table(name = NOTE)
public class Note{
#Id
#Column(name = "id_note")
private long id;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "id_fruit")
private Orange orange
}
Is the this Hibernate association mapping correct knowing that Orange is a subclass of Fruit? Will hibernate retrieve an Orange object from the table FRUIT_HIERARCHY? should i map it by putting a Fruit attribute and using casting when it comes to use an Orange object?
Thank you.

Atypic JPA OneToOne relation

I have a problem using JPA.
I have to tables:
-----------------
| TableA |
|---------------|
| ID: INT |
| ... |
| ESTATUS1: INT |
| ESTATUS2: INT |
-----------------
-----------------
| EstatusTags |
|---------------|
| COD: VARCHAR |---> COD and VALUE are a concatenated PK
| VALUE: INT |
| DESC: VARCHAR |
-----------------
EstatusTags is a table to store sets of pairs [VALUE, DESC], given a COD.
Before I use JPA, I used to query this kind of data in something like this:
SELECT ID, ESTATUS1, ESTATUS2, E1.DESC DESC1, E2.DESC DESC2
FROM TABLEA A
INNER JOIN ESTATUSTAGS E1 ON E1.COD = "a_estatus1"
AND E1.VALUE = A.ESTATUS1
INNER JOIN ESTATUSTAGS E2 ON E2.COD = "a_estatus2"
AND E2.VALUE = A.ESTATUS2
I'm trying to use JPA to model this using two entity classes:
#Entity
#Table(name = "EstatusTags")
public class EstatusTags implements Serializable {
#EmbeddedId
private ValueTagPK id;
#Column(name="VVA_DESC")
private String desc;
#Column(name="VVA_ORDEN")
private Integer orden;
}
#Entity
#Table(name = "TableA")
public class A implements Serializable {
#Column(name="ID")
private String desc;
#OneToOne(???)
private EstatusTag estatus1;
#OneToOne(???)
private EstatusTag estatus2;
}
I have strong doubts in how to model the relations. Can it be done with annotations? There is necesary the JPQL use to fit this structure?
I hope somebody could help me with this.
Thanks a lot.
The problem is that your entity model does not match the table structure.
In your entity model you have a one to one relation ship between A and EstatusTag whereas in your table model you have a relationship of one A and multiple Estatustags (for one value there may exist multiple Etatustags entries)
You overcome the problem that Table A does not have a cod column by adding something like a virtual cod column E1.COD = "a_estatus1" to your SQL Query.
What you can do is you map the value column of to two properties of EstatusTag one time to the composite pk and the other time to a single property in the following way . The simple value is made accessible via property access but marked as not updatable not insertable also the setter does not really work and is made private.
Remark: I don't know if that works with all JPA implementations - Tested with hibernate 4.3.8.
#Entity
#Table(name = "EstatusTags" )
#Access(AccessType.FIELD)
public class EstatusTag implements Serializable{
private #EmbeddedId ValueTagPK id;
#Column(name="VVA_DESC")
private String desc;
#Column(name="VVA_ORDEN")
private Integer orden;
#Column(name="value", updatable=false, insertable=false)
#Access(AccessType.PROPERTY)
public int getValue() {
return id.value;
}
private void setValue(int value) {
// only because otherwise hibernate complains about a missing setter.
}
}
#Entity
#Table(name = "TableA")
public class A implements Serializable{
#Id
#Column(name="ID")
#GeneratedValue(strategy=GenerationType.TABLE)
private int id;
#OneToOne()
#JoinColumn(name="estatus1",referencedColumnName="value")
public EstatusTag estatus1;
#OneToOne()
#JoinColumn(name="estatus2",referencedColumnName="value")
public EstatusTag estatus2;
}

jpa: inheritance with self references and non abstract superclass

In my current project I have a inheritance structure that looks like this:
#Entity
#Table(name="groups")
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorValue("G")
#DiscriminatorColumn(name="group_type")
public class Group{ //some annotations removed
private Long id;
private String name;
private Set<Subject> subjects;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="parent_group_id")
private Group parent; ##### tree parent ####
#OneToMany(cascade=CascadeType.ALL, mappedBy="parent")
private Set<Group> subGroups; ##### tree children #####
...
}
My Group objects can have kind of a tree like structure by containing a list of other Group objects.
As some groups are a bit special, there is a second class that extends this class:
#Entity
#DiscriminatorValue("C")
#Table(name="fix_groups")
public class FixGroup extends Group{
private Layout lay;
private Set<Person> instr;
...
}
I tried to use a joined multi table approach (as described here: http://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Joined.2C_Multiple_Table_Inheritance) but it seems not to work with a non abstract superclass like Group!
I get the following exception:
Caused by: java.lang.ClassCastException: org.hibernate.mapping.JoinedSubclass
cannot be cast to org.hibernate.mapping.RootClass
Is there a solution apart from declaring Group as abstract and making a new class Group2 that only extends it?
And if I did so, would this self-reference Set<Group> subGroups still cause problems?
I was able to cause this error by setting the ID in the subclass when it is already mapped in the parent class (in this case Group). For example in the parent class:
#Entity
#Table(name="groups")
#Inheritance(strategy=InheritanceType.JOINED)
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
...
and then setting the id in the subclass like so:
#Entity
#Table(name="sub_groups")
public class SubGroup extends Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
...
In this case, Group does not need to be abstract, but you can't define the id on the subclass.
Also, as a side note, if you are using Hibernate with an inheritance of type "join", then the discriminator column and value are not needed. Hibernate only utilizes those if using a single table. Please reference this post for further information:
Hibernate 4: persisting InheritanceType.JOINED discriminator column values

Mapping Multiple Classes to a Table in Hibernate, Without a DTYPE Column

I have two hibernate classes: a base class, and an extended class that has additional fields. (These fields are mapped by other tables.)
For example, I have:
#Entity
#Table(name="Book")
public class A {
private String ID;
private String Name;
// ...
}
#Entity
#Table(name="Book")
public class B extends A {
public String node_ID;
// ...
}
public class Node {
public String ID; // maps to B.node_ID
// ...
}
How do I map this in Hibernate? The hibernate documentation states three types of inheritence configurations: one table per class, one table with a type column, and a join table -- none of which apply here.
The reason I need to do this is because class A is from generic framework that's reused over multiple projects, and class B (and Node) are extensions specific to one project -- they won't be used again. In the future, I may have perhaps a class C with a house_ID or some other field.
Edit: If I try the above pseudo-code configuration (two entities mapped to the same table) I get an error that the DTYPE column doesn't exist. The HQL has a "where DTYPE="A" appended.
This is possible by mapping the #DiscriminatorColumn and #DiscriminatorValue to the same values for both classes; this can be from any column you use that has the same data regardless of which type (not sure if it works with null values).
The classes should look like so:
#Entity
#Table(name="Book")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="published")
#DiscriminatorValue(value="true")
public class A {
private String ID;
private String Name;
// ...
}
#Entity
#Table(name="Book")
#DiscriminatorValue(value="true")
public class B extends A {
public String node_ID;
// ...
}
For anyone who got here like me and does not want to have the dtype column but instead want to use the same table for more than one entity as is I would recommend using this
Basically you can create a Base like this
#MappedSuperclass
public abstract class BaseBook<T extends BaseBook> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
... any other variables, getters + setters
}
#Entity
#Table(name= "book")
public class BookA extends BaseBook<BookA>{
//Default class no need to specify any variables or getters/setters
}
#Entity
#Table(name= "book")
public class BookB extends BaseBook<BookB>{
#Column(name = "other_field")
private String otherFieldInTableButNotMapedInBase
... Any other fields, getter/setter
}
From the above we have created base super class which does not have any entity or table mapping. We then create BookA to be default with the Entity + Table mapping. From there we can create other Entities all extending from BaseBook but pointing to one table

Categories