I'm using JPA JOINED inheritance strategy with 3 abstract classes and 2 concrete.
Like this (code reduced for example purpose):
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
abstract class Employee {
#Id
private Long id;
private String firstName;
private String secondName;
}
#Entity
abstract class ProjectManager extends Employee {
#OneToMany(mappedBy="manager")
private List<Developer> developers;
}
#Entity
abstract class Developer extends Employee {
#ManyToOne
#JoinColumn(name="project_manager_id")
private ProjectManager manager;
}
#Entity
class JavaProjectManager extends ProjectManager {
private String someCustomProperty;
}
#Entity
class JavaDeveloper extends Developer {
private String skill;
}
This way, JPA creates 5 tables. But one of this tables, abstract ProjectManager it is empty. I mean, ProjectManager table only have ID column due to inheritance strategy.
My question is: how I can avoid this extra table for ProjectManager abstract class but keeping the same hierarchy of classes ?
I could not remove #Entity on ProjectManager class because I still need bidirectional relationship with Developer class.
Edit:
Also, I don't want move developers OneToMany from ProjectManager to JavaProjectManager, because I have more classes that extends from ProjectManager and need to have developers.
InheritanceType.TABLE_PER_CLASS does exactly what you want.
This type only creates/uses tables for non-abstract tables.
Read more about the various types here:
https://www.thoughts-on-java.org/complete-guide-inheritance-strategies-jpa-hibernate/
Related
I have a superclass that is an #Entity, something like this one:
#Entity
#Table(name = "utente")
public class Utente implements Serializable{
...
}
The subclass has just a #Transient field besides:
#Entity
public class UtenteSub extends Utente{
#Transient
private String newField;
}
To make it work, I should add #DiscriminatorValue, #Inheritance and add a field on the table.
This is a lot of work to do, taking into account that all I need in the subclass is just a #Transient field (I need it to "check" the object Utente after its "submission" in a form).
Is there a better and easier way to extend the #Entity in my scenario?
Thank you.
You could try creating an abstract base class UtenteBase:
#MappedSuperClass
public abstract class UtenteBase implements Serializable
{
//all mapped columns go here
}
All your mapped columns which were in Utente before are now in this class.
You can then extend this class with your two above mentioned classes:
#Entity
#Table(name = "utente")
public class Utente extends UtenteBase
{
public Utente {}
}
#Entity
#Table(name = "utente")
public class UtenteSub extends UtenteBase
{
#Transient
private String newField;
}
The class Utente is the concrete implementation class and is used for the communication with the database.
Both classes are in the same inheritance tree and you don't need to add a DiscriminatorValue and change the table.
Writing the case it will be more simple to explain.
I am using Seam 2.3.1 v Hibernate JPA 2.0 and in our project. I have a base Person Entity Class.
#Entity
#Name("person")
#Inheritance(strategy = InheritanceType.JOINED)
#Table(name = "person")
public class Person extends BaseEntity {
private String name;
private String surName;
private String email;
private String phone;
// getter & setters
}
And I have 3 more Entity extends from Person as #Inheritance(strategy = InheritanceType.JOINED): Personel, Musteri, DisPaydas
#Entity
#Name("personel")
public class Personel extends Person {
private String appellation;
// getter & setters
}
I want to List personels, musteris and dispaydas in my bean however when I set them in my Group Entity, I want to save them as Person.
In fact in DB there is no difference between person_id and personel_id, they are same. However when I listing it, they are List<Personel>
In summary:
I want to get List<Person> from List<Personel>
or Person from Personel object.
You're going to have to define an #Id and #Column in the Person class for the person_id.
However, since the column has a different name in the child entity, you'll need to change it using an #AttributeOverride to point to the personel_id #Column.
It couldn't hurt to use a #DiscriminatorColumn in the parent and #DiscriminatorValue in the children, but I don't think Hibernate requires those.
I have an existing table without discriminator column and I need to map it with single table hierarchy, how to map this?
here is my table
vehicle
========
vehicle_id
manufacturer
load_capacity
passenger_capacity
I have 3 classes
Vehicle.java
vehicleId;
manufacturer;
TransportationVehicle.java
loadCapacity;
PassengerVehicle.java
passengerCapacity;
If you have no discriminator, then you need another condition to distinguish TransportationVehicle and PassengerVehicle. I guess in your case you could use:
TransportationVehicle: loadCapacity IS NOT NULL
PassengerVehicle: passengerCapacity IS NOT NULL
As JPA inheritance always needs a discriminator, you will have to use #MappedSuperclass and two #Entity classes with a corresponding #Where annotation:
#MappedSuperclass
public abstract class Vehicle {
#Id
private Long vehicleId;
private String manufacturer;
}
#Entity #Where(clause = "loadCapacity IS NOT NULL")
public class TransportationVehicle extends Vehicle {
private int loadCapacity;
}
#Entity #Where(clause = "passengerCapacity IS NOT NULL")
public class PassengerVehicle extends Vehicle {
private int passengerCapacity;
}
Major disadvantage of this approach compared with real JPA inheritance: You can't reference the mapped superclass in JPA - neither in queries (SELECT v FROM Vehicle v) nor in another entity (#OneToOne Vehicle vehicle).
One way to do it is use #MappedSuperclass on the Vehicle class and then map TransportationVehicle and PassengerVehicle to the same table.
This way you will inherit the mapped fields from Vehicle without having to map it as an entity.
I have one question related to JPA relations.
Is it possible to define one relation to different classes?
Ej: Foo has a one-to-one relation (or many-to-one) with Boo or Too class (both can extend the same abstract class) but not a relation with both at the same time.
Thanks!
More details
It will be something like:
#Entity
class Foo {
#Id
int id;
#OneToOne(fetch=FetchType.LAZY)
#JoinColumn(name="MOO_ID")
Moo moo;
}
Interface Moo{}
#Entity
class Too implements Moo{}
#Entity
class Boo implements Moo{}
And my database needs only one reference to the correct table Too or Boo.
If you made Moo an abstract class and specified an inheritance strategy you could achieve this.
i.e.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Moo {
#Id int id;
}
and then for Foo:
#Entity
class Foo {
#Id
int id;
#OneToOne(fetch=FetchType.LAZY)
#JoinColumn(name="MOO_ID")
Moo moo;
}
And
#Entity
class Too extends Moo{}
#Entity
class Boo extends Moo{}
That way the Moo reference can be either Boo or Too.
You should also thenn choose whichever inheritance strategy works best for your scenario. From TABLE_PER_CLASS, SINGLE_TABLE and JOINED.
I have searched quite a bit through other SO questions without luck, possibly due to me using the incorrect search terms.
I would like to create an entity (Note), that can be "attached" to any other Entity in our inheritance tree.
eg:
#Entity
class Note extends AbstractEntity {
String title
String message;
AbstractEntity relatedItem;
}
#Entity
class EntityOne extends AbstractEntity {
}
#Entity
class EntityTwo extends AbstractEntity {
}
I know that I could do the following:
#Entity
class Note extends AbstractEntity {
String title
String message;
}
#Entity
class EntityOne extends AbstractEntity {
List<Note> notes;
}
#Entity
class EntityTwo extends AbstractEntity {
List<Note> notes;
}
but this will then result in tables like:
Note - ID, title, message
EntityOne_Note - entityOne_ID, note_ID
EntityTwo_Note - entityTwo_ID, note_ID
and requires me to update the entities if we wish to add note support to them.
For some reason it just feels better to have a table like:
Note - ID, title, message, relatedItem_ID, relatedItem_DTYPE
I dont even mind a single extra table:
Note - ID, title, message
AbstractEntity_Note - relatedItem_ID, relatedItem_DTYPE, note_ID
thoughts?
It depends on how many relatedItem_DTYPE you have, if they are few (for example 2) you can use an approach like this
#Entity
class Note extends AbstractEntity{
public String title
public String message;
#ManyToOne
EntityOne e1;
#ManyToOne
EntityTwo e2;
}
If you wish to have the references to the notes in Entities classes, just add a field to keep trace of the reverse relation.
You will end up to classes like these:
#Entity
public class EntityOne{
...
#OneToMany(mappedBy="e1")
public List<Note> notes;
}
#Entity
public class EntityTwo{
...
#OneToMany(mappedBy="e2")
public List<Note> notes;
}
Or you can try to create the inheritance using the InheritanceType.TABLE_PER_CLASS and see how Hibernate handle that :D.
By the way keep in mind that just saving the couple relatedItem_ID, relatedItem_DTYPE means that a note can belongs only to one instance of a particular type.