I have this strange hierarchy:
Class A is abstract (but it is an entity)
Class B (abstract) and C both extend class A (TABLE_PER_CLASS).
Class B is also extended by classes D and E but this time it is JOINED.
I want the ID of the A class to be the ID of all others.
Can this be done?
I get strange errors of IDs. can any one show me how to map?
This is how I did it:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class A {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
protected Integer id;
}
Class C:
#Entity
#Table(name = "managers")
public class C extends A {
Class B:
#Entity
#Table(name = "bb")
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
public abstract class B extends A {
Class C,D:
#Entity
#Table(name = "cc"/"dd")
#DiscriminatorValue("CC"/"DD")
public class C (or D) extends B {
While mixing inheritance strategies in an inheritance tree can be sort of accomplished (https://stackoverflow.com/a/3916998/131929 refers to Java Persistence with Hibernate
-> 5.1.5 Mixing inheritance strategies (p207-p210)) I, and everybody else I know, advise against it.
Sidenote, I suggest you always use #MappedSuperclass rather than #Entity for abstract classes.
Related
I have two tables A and B:
#Entity
public class A {
}
#Entity
public class B {
private final A a;
private String someBSpecificField;
}
Entity A is already Coded nicely and mapped to an existing table. My job is to create B and for some reason I prefer composition over inheritance between A and B. At the same time I want to have single table for A and B to avoid joins when reading. Can I do like this:
#Entity
#Table(name = "a")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "a_type_enum", discriminatorType =
DiscriminatorType.INTEGER)
#DiscriminatorValue("100")
public class A {
}
#Entity
#Table(name = "a")
#DiscriminatorValue("500")
public class B {
private final A a;
private String someBSpecificField;
}
If the type is a complex object then you need to annotate that type with #Embeddable and use it in your #Entity class.
if you want to override the attribute names for your #Embeddable class so they have different column names, you can do so with the #AttributeOverrides annotation.
I have the following class structure:
I would like to generate the following three tables with hibernate:
PlanItem: with all its attributes
Task: with all its attributes and its child attributes
Stage: with all its attributes
I tried to mix the inheritancetypes but it didn't work:
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class PlanItem {...}
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Stage extends PlanItem {...}
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Task extends PlanItem {...}
#Entity
public class HumanTask extends Task {...}
#Entity
public class ProcessTask extends Task {...}
#Entity
public class CaseTask extends Task {...}
I already experimented with secondary tables and got more or less the desired result:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class PlanItem {...}
#Entity
#SecondaryTable( name = "Stage" )
public class Stage extends PlanItem {...}
#Entity
#SecondaryTable( name = "Task" )
public class Task extends PlanItem {...}
#Entity
#SecondaryTable( name = "Task" )
public class HumanTask extends Task {...}
#Entity
#SecondaryTable( name = "Task" )
public class ProcessTask extends Task {...}
#Entity
#SecondaryTable( name = "Task" )
public class CaseTask extends Task {...}
But I was wondering if a more elegant and simple solution exists?
That's currently not possible, see the following issue for further information. I think that your "hack" with using secondary tables is currently the best you can get.
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'm using EJB 3 with Hibernate 4 on Weblogic 10.3.4.
I have a problem when I try to select an entity based on a property that doesn't exists in its parent entity:
I have in my system something like this: A basic abstract VehicleDefinition class and two concrete subclasses - CarDefinition and TruckDefinition.
Also, I have a basic abstract VehicleInstance and two concrete subclasses - CarInstance and TruckInstance.
In VehicleInstance I have a VehicleDefinition field.
In the TruckDefinition class I map a field (Height) that doesn't exists In VehicleDefinition or in CarDefinition. The problem is that with the mentioned mapping, I can't use an HQL to select a TruckInstance by a the field of TruckDefintion (i.e. A TruckInstance by height), because TruckInstance only "knows" VehicleDefinition, not TruckDefinition.
The mappings goes something like this:
#Entity
#Table(name = "VEHICLES" uniqueConstraints = {#UniqueConstraint(columnNames = {"TYPE_NAME"}) })
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "VEHICLE_TYPE", discriminatorType = DiscriminatorType.INTEGER)
public abstract class VehicleDefinition {...}
#Entity
#DiscriminatorValue("222")
public class CarDefenition extends VehicleDefinition {...}
#Entity
#DiscriminatorValue("555")
public class TruckDefenition extends VehicleDefinition{
...
private Integer mHeight;
#Column(name = "TRUCK_HIGHT")
public Integer getHeight()
{
return mHeight;
}
}
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorFormula("CASE WHEN 222 = (SELECT a.VEHICLE_TYPE FROM VEHICLES a WHERE a.id = VEHICLE_ID) THEN 222 ELSE 555 END")
#Table(name = "VEHICLE_INSTANCES" uniqueConstraints = {#UniqueConstraint(columnNames = {"VEHICLE_ID", "LPLATE"}) })
public abstract class VehicleInstance {
...
private VehicleDefinition mDefinition
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "VEHICLE_ID" referencedColumnName = "ID", nullable = false)
public VehicleDefenition getDefinition()
{
return mDefinition;
}
}
#Entity
#DiscriminatorValue("222")
public class CarInstance extends VehicleInstance {...}
#Entity
#DiscriminatorValue("555")
public class TruckInstance extends VehicleInstance {...}
I tried to refactore he classes, making getDefinition in VehicleInstance abstract, and having TruckInstance and CarInstance implement, both returning their repectivetypes, but then I couldn't figure out how two map the new methods. Should I keep the original annotations at VehicleInstance? Should both of them point to VEHICLE_ID? Every combination I tried seemed to fail.
So in conclusion - How can I map VehicleInstance, CarInstance and TruckInstance so that I can select in HQL a TruckInstance based on its Height property?
Thanks in advance!
We create our tables automaticly via Hibernate by assigning:
#Table(name = "some_table")
That used to work for "normal" entities. But when we have an abstract base class:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class PersonBankAccount extends AbstractPersistable<Long> {
that is extended by
#Entity
#Table(name = "person_bank_account")
public class PersonBankAccountSimple extends PersonBankAccount {
The resulting table in the database is named
personbankaccount
What is going on here?
The autogenerator says:
table not found: PersonBankAccount
when first creating it and on rerun he says:
table found: personbankaccount
Like I said, for normal tables everything works fine.
Shouldn't be the name of table in the base class instead.
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#Table(name = "person_bank_account")
public class PersonBankAccount extends AbstractPersistable<Long> {