I have 3 classes:
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue
private Long id;
...
}
#Entity
public class Person extends BaseEntity {
private String name;
...
}
#Entity
#AttributeOverride(name = "id", #Column = (name = "idStudent"))
public class Student extends Person {
private float avgGrades;
...
}
I would like to override ID property so in Student table there would be a idStudent column instead of id. Unfortunately, the code above doesn't work. It looks like #AttributeOverride only works for the class you extending (and no one step further). Is there any way to override attribute name in situation I've descried (override attribute in class which exteds our class being extended) ?
Your problem is very easy to understand, if you know what the default inheritance type is: SINGLE_TABLE.
That means all entities that extending Person are in the same table. And thus Person already defines the ID column. Because you would otherwise violate the contract of the primary key column of your Person table.
I cite the JavaDoc of #AttributeOverride as well:
May be applied to an entity that extends a mapped superclass or to an embedded field or property to override a basic mapping or id mapping defined by the mapped superclass or embeddable class (or embeddable class of one of its attributes).
It always helps to read the JavaDoc first, before asking questions here.
What can you do about it? Make your Person a #MappedSuperclass (or create a BasePerson that is one).
Related
I'm trying to override a property of an embedded column existing in the superclass of an entity.
My entities look like this:
#Embeddable
public class Key {
#Column
private String a,
#Column
private String b
}
#MappedSuperclass
public abstract class Superclass {
#EmbeddedId
private Key key;
}
#Entity
#Table(name = "my_entity")
#AttributeOverride(name = "b", column = #Column(name="renamed_b"))
public class MyEntity extends Superclass {
}
I have tried using AttributeOverride on MyEntity, but it doesn't do anything.
It would work if I would move the AttributeOverride annotation on the embedded field, but I cannot modify the superclass.
Is there any solution?
Look, read documentation carefully:
To override mappings at multiple levels of embedding, a dot (".")
notation form must be used in the name element to indicate an
attribute within an embedded attribute.
The name "b" is incorrect.
You should use "key.b"
#Entity
#Table(name = "my_entity")
#AttributeOverride(name = "key.b", column = #Column(name="renamed_b"))
public class MyEntity extends Superclass
}
I have couple of entities, Person and PersonSnapshot. PersonSnapshot is same as Person, except for, it has its own primary key.
I would like use Java class hierarchy so that I need not redefine property names, but I am not able to get them to work as the two tables will have different "#Id" properties.
#Entity
#Table(name = "Person")
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
class Person {
#Id
private int id;
#name
private String name;
}
I need to store its snapshot as in
#Entity
#Table(name = "Person_Snapshot")
class PersonSnapshot extends Person {
#Id
private int snapShotId;
}
I don't want to create an abstract MappedSuperClass for common attributes as I will end up with 3 classes. Is there any way achieve the same result with just these two classes ?
Move everything that is common between the two classes into a superclass and annotate it with #MappedSuperclass. For more details see for example this: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html
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 an entity that is super class
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Table(name = "super_class")
public abstract class SuperClass implements Serializable {
#Transient
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long id;
public abstract void initDefaultValues();
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
and some subclasses that extend the SuperClass.
#Entity
#Table(name = "Subclass1")
public class Subclass1 extends SuperClass{
private static final Logger log = LogManager
.getLogger(Subclass1.class);
#Transient
private static final long serialVersionUID = 1L;
// testcase configuration tab
private String configurationTabTestServer;
private String umtsRelease;
}
The other classes look the same.
I used to have them SINGLE_TABLE for inheritance type but we wanted each concrete class to have each own table. Because of TABLE_PER_CLASS I had to use GenerationType.TABLE.
I also have an entity class that has a foreign key to the super class
#Entity
#Table(name="myother_entity")
class Entity1{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#OneToOne(cascade = CascadeType.ALL)
private SuperClass superclass;
//more fields
}
I used an abstract class because I have one Entity1 class that could have different type of Superclass. We didn't want to create different Entity1 and Entity2 and Entity3 etc classes for each subclass. So we created one Entity1 class that can have a field of type SuperClass, that could point to any of the subclasses.
On my program I create many Entity1 intances that some of them that have different type of superclass as field value. Each could be of type subclass1 or subclass2 etc. At first we used to have one single table for all subclasses. Everything worked fine. But after we decided to split our tables this is what it happens. When I edit any Entity1 instance, that has already SuperClass field set(using one of the sub classes), and save it (merging it) then it creates a new instance of my Subclass associated with my Entity1 instance, and then saves it to the database. So I have two records now on the table of the subclass. This didn't happen when we used a SINGLE_TABLE inheritance type. Is this normal behaviour for JPA and hibernate?
Please, first consider this: DiscriminatorColumn and DiscriminatorValue annotations are specific to single-table approach. So they aren't to be used in table-per-class mappings.
Now, let's go to the issue:
In table-per-class mapping, there will be two records with same ID: one in a parent table, other in a child table.
As I understood, in your case, two records are being written in the child table, right? If so, the problem must be when you load the Entity1 data from the database. The property "superclass" must have its ID set. You can use eager or lazy loading for this. And check if that property is properly loaded (in debug mode) with its correct ID set before saving it.
Another way is to disable "cascade persist/merge" and to save the entities separately. It can provide more security to your data.
You can find more information here: http://docs.oracle.com/javaee/6/tutorial/doc/bnbqn.html
I have the following setup with Spring Data JPA and Hibernate as the persistence provider. All of my entities inherit from a base class
#MappedSuperclass
public class BaseEntity {
#Id
private id;
#Version
private String version;
//more common fields
}
For example:
#Entity
public class Foo extends BaseEntity {
}
This leads to a primary key column with name "ID" to be generated on the "FOO" table. I would like to change the naming of the primary key column. It should reflect the name of class or table. So it should be "FOO_ID" instead of just "ID".
I know that I could do this statically by using #Column(name = "FOO_ID"). But that would mean I have to do this for every Entity. Is there a more dynamic way to achieve this?
I know this is an old question, but stumbled across this looking for an answer... Eventually found this solution elsewhere:
#Entity
#AttributeOverride(name="id", column=#Column(name="FOO_ID"))
public class Foo extends BaseEntity {
}
All your subClasses will have the same ID column name because of the inheritance, you can specify a common id colum name for all subClasses in the Base entity Class
Why use inheritance then? Just do it without inheritance.
You could use getters/setters to rename your fields
Ex:
class Foo {
private Long id;
public Long getFooId() {
return this.id;
}
public void setFooId(Long fooId) {
this.id = fooId;
}
}