How can I provide a relationship between two derived class from the same class on hibernate.
I have a class named BaseEntity and it has some attributes that every derived class will have too, such as updateDate,updateID.
And I have two classes derived from that BaseClass named Salary and Employee. And those classes must have a relationship between them which is one-to-one. How can I accomplish that? I have been reading about Hibernate but I haven't seen anything related to this, or I am thinking in a totally wrong way.
It is simple.You can declare a salary variable in Employee class and annotate it with #OneToOne annotation.
#OneToOne
private Salary salary;
Related
I am trying to design a database schema so that it is applicable for the Hibernate's Table Per Class inheritance strategy. So, I will not let Hibernate to generate the tables, instead I need to design them myself in Liqibase but in such way that Hibernate can use them with that strategy.
My entity classes should look like this.
Vehicle.java
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Vehicle {
#Id #GeneratedValue
private int id;
private String name;
private String brand;
}
Car.java
#Entity
public class Car extends Vehicle {
private String oil;
}
Bike.java
#Entity
public class Bike extends Vehicle {
private String frame;
}
Now, I know that that this strategy means that all the fields are in all tables, but I am not sure about two things.
1) Do I need to include the ID in the derived tables?
2) Do I even need a Vehicle table in the DB, since it will actually never be used as an entity (rather just an abstract class)?
I'd appreciate if someone could clear that for me.
Now, I know that [the table-per-concrete-class] strategy means that all the fields are in
all tables,
Well no, you seem to be confused. With InheritanceType.TABLE_PER_CLASS, each concrete entity class E maps to a table that contains columns corresponding to all the fields of E, including inherited ones, but not including fields of entities that are not superclasses of E.
This is to be contrasted with InheritanceType.SINGLE_TABLE, in which all entity types in a whole inheritance hierarchy map to the same table, which then necessarily contains a column for each property of each entity in the hierarchy (without duplicating inherited fields).
Note also that it is odd that your Vehicle entity contains fields with the same names as fields of its subclasses. Java fields are not polymorphic, so this is unlikely to be what you want. It's certainly unnecessary.
but I am not sure about two things.
1) Do I need to include the ID in the derived tables?
Supposing that you stick with TABLE_PER_CLASS, yes, each entity table needs to provide a column for each persistent property of the corresponding entity class, including those inherited from superclasses. That includes id.
2) Do I even need a Vehicle table in the DB, since it will actually
never be used as an entity (rather just an abstract class)?
Not if you actually declare it abstract, but if you leave it concrete, then yes, you need a table for it. And that makes sense, because in that case you could have Vehicle entities that are neither Cars nor Bikes.
Hibernate schema generation tool should be able to generate your schema if you annotate your entities correctly.
In this case Vehicle table which be generated since your entity class is concrete. You need to define the class as abstract.
All the fields defined in the superclass (including the #Id) will be copied in the corresponding child class tables. There is a limitation though regarding id auto generation. You cannot use the table per class inheritance strategy with the GenerationType.IDENTITY strategy since the generated keys should be unique across all tables. Identity creates unique ids per table
Make sure the Generation.AUTO strategy does not map to the IDENTITY strategy for your RDBMS (You can specify a strategy explicitly eg GenerationType.TABLE to override the default)
A MappedSuperclass uses inheritance for field and code reuse.
In addition we leverage some composition via Embeddable feature provided Hibernate
#Embeddable
public class Department {
private long deptId;
private String name;
private String description;
}
#Entity
#Table(name="CSE_DEPT", schema="test")
public class CSEDepartment{
#Embedded
private Department dept;
}
What is difference between #MappedSuperclass and #Embeddable and what is appropriate situation where they use.
#MappedSuperClass is good when we want to share some state between different entities so they will have the same fields and you can reuse the fields in your different entities. Generally it is created as a abstract class and you cannot create its own instance. You use this when you want to mimic the 'Is A' relationship. It cannot be used as a target for associations.
#Embeddable is used to map composite value types. #Embeddable class is used as one of the field type with in our entities. you can use this when you want to mimic 'Has A' relationship.
The case you have stated in the question, it may not be suitable for any. because both MappedSuperClass and Embeddable cannot be an entity..(you have departmentid in the department class which i am assuming should be a primary key).
For your case better is to use #OneToOne entity association because cse department will have a uniqu id name and desc. you dont want to have 2 csedepartment in one college.
I am using Play Framework 1.2.4 with PostgreSQL and JPA. I would like to have a Model hierarchy and see that there are some alternatives to doing this.
I have a base class (which is abstract) and two concrete classes extending this base class. I don't want to persist this base class while I want to have concrete classes. In the base class, I have another Model classes as properties, in other words, I have #ManyToOne relationships in my base class.
My question is what is the best way of implementing this? Using #MappedSuperclass or #Inheritance with TABLE_PER_CLASS strategy? I am a bit confused as they seem virtually equivalent.
I also have some concerns about querying and performance issues that I might face in future.
MappedSuperClass must be used to inherit properties, associations, and methods.
Entity inheritance must be used when you have an entity, and several sub-entities.
You can tell if you need one or the other by answering this questions: is there some other entity in the model which could have an association with the base class?
If yes, then the base class is in fact an entity, and you should use entity inheritance. If no, then the base class is in fact a class that contains attributes and methods that are common to several unrelated entities, and you should use a mapped superclass.
For example:
You can have several kinds of messages: SMS messages, email messages, or phone messages. And a person has a list of messages. You can also have a reminder linked to a message, regardless of the kind of message. In this case, Message is clearly an entity, and entity inheritance must be used.
All your domain objects could have a creation date, modification date and ID, and you could thus make them inherit from a base AbstractDomainObject class. But no entity will ever have an association to an AbstractDomainObject. It will always be an association to a more specific entity: Customer, Company, whatever. In this case, it makes sense to use a MappedSuperClass.
#MappedSupperclass is different than the #Inheritance annotation.
#MappedSuperclass tells the JPA provider to include the base class persistent properties as if they were declared by the child class extending the superclass annotated with #MappedSuperclass.
However, the inheritance is only visible in the OOP world, since, from a database perspective, there's no indication of the base class. Only the child class entity will have an associated mapped table.
The #Inheritance annotation is meant to materialize the OOP inheritance model in the database table structure. More, you can query a base class annotated with #Inheritance but you can't do that for a base class annotated with #MappedSuperclass.
Now, the reason why you'd want to use the #Inheritance JPA annotation is to implement behavior-driven patterns like the Strategy Pattern.
On the other hand, #MappedSuperclass is just a way to reuse both basic properties, associations, and even the entity #Id using a common base class. Nevertheless, you can achieve almost the same goal using an #Embeddable type. The only major difference is that you can't reuse an #Id definition with #Embeddable, but you can do it with #MappedSuperclass.
I was wondering if it makes any sense (or even if it is correct) to annotate every class of a hierarchy with #Inheritance. For example, suppose we have the following simple hierarchy:
public class A { ... }
public class B extends A { ... }
public class C extends A { ... }
In order to persist objects of these classes, we would annotate class A as follows:
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class A { ... }
My question is, do we need to add the #Inheritance annotation to class B and C also? As the Javadoc says "It is specified on the entity class that is the root of the entity class hierarchy." so my potential answer would be, no! But if we do annotate them, does this have any meaning at all, or is it completely ignored?
Thanks
You need to add #Inheritance annotation to subclasses if you need to use not default InheritanceType.
As you know, there is 3 InheritanceTypes supported. Table per class hierarchy, Table per subclass and Table per concrete class.
InheritanceType.SINGLE_TABLE is used by default, and all of your parent class and subclasses objects will be placed in one table.
If you want to use InheritanceType.JOINED or InheritanceType.TABLE_PER_CLASS, you need to add #Inheritance annotation.
You create a bidirectional one-to-one relationship using fields on
both classes, with an annotation on the child class's field to declare
that the fields represent a bidirectional relationship. The field of
the child class must have a #Persistent annotation with the argument
mappedBy = "...", where the value is the name of the field on the
parent class. If the field on one object is populated, then the
corresponding reference field on the other object is populated
automatically.
What can a bidirectional one-to-one relationship do?
Can someone give me a example?
And why I always got this error.
Class "com.example.datastore.Employee" has field "contactInfo" with
"mapped-by" specified as "contactInfo". This field doesnt exist in the
target of the relation ("com.example.datastore.ContactInfo")!!
Thanks in advance!
I try to answer from what I learnt from Hibernate/JPA (which I think is similar)
Seems that your ContactInfo do not have relationship to Employee. To use what you described as an example for bidirectional one-to-one relationship, you will see something like (it is probably not syntactically correct, just to give u idea):
public class Employee {
//... other relationship or fields
#OneToOne(mappedBy="employee") // the field in ContactInfo
private ContactInfo contactInfo;
}
public class ContactInfo {
#OneToOne
#JoinColumn("EMP")
private Employee employee;
}
The 'real' relationship in persistence layer is in fact dominated by ContactInfo.employee. Setting Employee.contactInfo will not cause persistence layer to contain correct data.
I wish this help and applies to JDO too. :P
It sounds like you have a one-to-one of Employee to ContactInfo. An employee has exactly one contact info, and a contact info belongs to exactly one employee. That's a bidirectional one-to-one. Your error is occurring because "mapped-by" needs to specify the name of the property of the other object that refers back to this one. For example, if you have
class Employee {
private ContactInfo contactInfo;
}
class ContactInfo {
private Employee employee;
}
then when you map the Employee.contactInfo property, its "mapped-by" would be "employee" because that's the property that it's "mapped by" in the ContactInfo.
First the Error What the error is saying is that contactInfo is not a field of class com.example.datastore.ContactInfo . They field mapped by must be a field\property of the class you are mapping to .
Second The concept of Bi-Direction Mapping
It's just that two tables in one-to-one or one-to-many relationship where both entities will have knowledge of the other s. You do not always need it and that depends on situation and context but generally is more common to have bi-directional one to many than one to one.
You question is about one-to-one so to give you an example of when both entities need to know about each other from Hibernate docs A bidirectional one-to-one association on a join table is possible, but extremely unusual. But if you really wanted to be able to get either entiy from which ever table (which is very rare) then you create bi-directional one to one
Person and Address just to quote an example