I have a Hibernate, spring and GWT application. I have two tables: Employee and user.
Every user is an employee and thus I have One To One relation in the database( they are joined by the primary keys) and thus User extends Employee. Things work fine when I insert user first, it auto inserts parents correctly. However, the problem is when I try to add the user entry for an existing employee, which instead of inserting the user record with the parent Id, it re-creates the employee record and user record.
#javax.persistence.Entity
#javax.persistence.Table(name = "User")
#Inheritance(strategy = InheritanceType.JOINED)
#PrimaryKeyJoinColumn(name="Id")
public class User extends Employee
{ .... }
#Reflectable(assignableClasses = true, superClasses = true)
#javax.persistence.Entity
#javax.persistence.Table(name = "Employee")
#Inheritance(strategy = InheritanceType.JOINED)
#PrimaryKeyJoinColumn(name="Id")
public class Employee
{
#Id
#GeneratedValue
#Column(name="Id")
public Integer getId()
{
return id;
}
}
Is this the right way to do things? How can I overcome this?
Thank you very much.
Update 1:
By Add user to it, I mean that I want to create a user with the same Id as employee.
which should basically become:
Insert into User (Id, username,..) Values (1, "Username", ...)
I do not think the existing mapping makes any sense.
I would suggest scrapping the inheritance and mapping a one-to-one (or one-to-many) relationship between Employee and say UserAccount.
I think that better reflects your model.
An employee may or not be a user of a system. Employees who are have a user account on that system.
If more systems amy be added in future then use a one-to-many. Employees have user accounts on zero, one or more systems.
Something doesn't sit right the first time I read your description and confirmed by your code snipet.
A few things you mentioned I break down into points:
Every user is an employee
I have OneToOne relation
User extends Employee
when I try to add the user entry for an existing employee
Just doesn't make sense.
Every User is an Employee and User extends Employee makes sense (somewhat)
but then why did you mention a One-to-One relation? There's no relation here, as also shown through your code.
A User is an Employee, but User does not own an Employee nor does an Employee own an User attribute (which is what "relationship" means).
Relationship is for example: an Employee has an Address, or a User has PermissionList.
And in the last point, when you said "add the user entry for an existing employee" shows that a User in this case supposed to be an attribute of an Employee and probably a List and not one-to-one (since you want to "add" to it).
Although if you step back, it doesnt make a lot of sense either because Employee does not own a User in the English sense.
A subclass / superclass is usually to describe a specific type of a more abstract type. eg. Dog is a subclass of an Animal because Dog is a specific type of Animal. Which I don't think what you want here.
I think you need to re think your design, and may be describe what you are trying to do.
Related
I am new to Spring data jpa and trying to understand #OneToOne mapping.
Let's say I have a Employee entity and a Company Entity, If I want to map these 2 entities, then I can use one to one mapping on Employee entity which means one employee can belong to one company only.
Is this understanding wrong?
If one employee belongs to one company(lets say XYZ) then the company(XYZ) cannot be mapped to a different employee?
I have read few posts but not completely understood.
#OneToOne represents that there is only one Object of Entity related to the other Entity
if we have Employee and Passport Entity so only One Passport related to One Employee
and for sure one One Object of Employee related to One Object from Passport
#Entity
Public class Employee
{
#OneToOne
private Passport passport;
}
so from Employee i can get his Passport
#Entity
Public class Passport
{
#OneToOne
private Employee employee;
}
and from Passport i can get The Employee.
Mapping is nothing but defining the relationship between two entities/objects and it is just like stating 5>4, 10=10, 6<8. The numbers here (5,4,10,6 and 8) are the entities and the symbols (>, = and <) are the relationships/mapping between them.
We do the same with mappings in hibernate. Note down the two entities and put in between them the relationship (mapping) them in the way it makes more sense.
Father OneToMany Child (Father can be One, To Many child/children)
Child ManyToOne Father (Child/Children can be Many, To One Father)
Employee ManyToOne Company (Employee can be Many, To One Company)
Company OneToMany Employees (Company can be One, To Many Employee(s))
Address OneToOne Employee (Address can be One, To One Employee)
Employee OneToOne Address (Employee can be One, To One Address)
The relationship should make sense. Which means it should make sense when you look at the relationship from each of the both sides of the relationships (One child Many Fathers doesnt make sense but One Father many child/children does)
Say an employee can be mapped to a Company that is one to one mapping keeping Employee as owner of the relationship. Whereas if you view Company as owner of the relationship, that it is One to Many.
Case 1 : Employee as Owner
#Entity
Public class Employee
{
#ManyToOne
private Company company;
......
}
#Entity
Public class Company
{
#OneToMany(mappedBy="company") \\ mappedBy is used to say that Employee is owner and
\\it should match variable name company
private List<Employee> employee;
......
}
Yes, you are correct.
If you want the Company to have multiple Employees, then you want a ManyToOne relationship between Employee and Company, and a OneToMany relationship between the Company and employee.
Actually, in this case, You must use one to many relationship.
you can simply use the #ManytoOne annotation in Company Entity that related to Employee Entity.
Specifies a single-valued association to another entity class that has many-to-one multiplicity. It is not normally necessary to specify the target entity explicitly since it can usually be inferred from the type of the object being referenced. If the relationship is bidirectional, the non-owning OneToMany entity side must used the mappedBy element to specify the relationship field or property of the entity that is the owner of the relationship.
Visit https://en.wikibooks.org/wiki/Java_Persistence/ManyToOne for more information and samples.
What's the use of #Embedded and #Embeddable In Hibernate ? Because every example i found on internet is inserting data inside of a single table and to do that using two different class. My point is if I am using a single table then I can map all the columns inside of a single class then why should i use different class. and if We use two different table then there is one-to-one and one-to-many hibernate relationship.
There are two types of objects in Hibernate
1. Value Object
2. Entities
Value Objects are the objects which can not stand alone. Take Address, for example. If you say address, people will ask whose address is this. So it can not stand alone.
Entity Objects are those who can stand alone like College and Student.
So in case of value objects preferred way is to Embed them into an entity object.
To answer why we are creating two different classes: first of all, it's a OOPS concept that you should have loose coupling and high cohesion among classes. That means you should create classes for specialized purpose only. For example, your Student class should only have the info related to Student.
Second point is that by creating different classes you promote re-usability.
When we define the value object for the entity class we use #Embeddable.
When we use value type object in entity class we use #Embedded
suppose we have employee table annotated with #entity and employee has Address so here i dont want to create two tables i.e employee and address, i just want create only one table i.e employee not Address table then we need to declare Address instance in Employee and add #embedable annotation on top of Address class, so finally we get table employee with its record and address records as well in single employee table
One entity can be embedded in another entity. The attributes of an entity can be common attributes of more than one entity. In this case there can be one embeddable entity. And this embeddable entity can be embedded in more than one entity.
Let's consider an example. We have one Animal entity, which has name and location attributes. Now two different entities Lion and Elephant can have Animal attributes just by embedding the Animal entity. We can override the attributes. In Animal entity there is location attribute and in Elephant there is place attribute. So with the help of #AttributeOverrides we can do like below:
#AttributeOverrides({ #AttributeOverride(name = "location", column = #Column(name = "place")) })
I have 2 tables.
Student (id,name,class_id)<br>
class(id,name)
student relates to class table through class_id
after using hibernate and generate into object, I'll have 2 objects
Student { int id; String name; Class class }
Class {int id; String name; Set<Student> student}
I want to save student information using hibernate (session.save(student)). However, I have to call class through class_id. Therefore, is there anyway to save the student without get the class object using hibernate?
This is just an example, I have work with a database that a table has many relationship with the others, and it's a pain for me.
I guess
student.setClass(null);
session.save(student);
should help. Although I am not sure what ". However, I have to call class through class_id" means.
You may be looking at unidirectional one-to-many relationship(based on class definitions given above) from class to student. You also need to understand cascades. Go through this, and this to learn about associations as you said you have similar scenarios.
What is the difference between #Embedded annotation technique and #OneToOne annotation technique because in Embedded the java class contain "Has a" relationship in class and with the help of #Embedded annotation we persist the has a object in database. and in OneToOne relationship we also persist the has a object in database.
#OneToOne is for mapping two DB tables that are related with a one to one relationship. For example a Customer might always have one record in a Name table.
Alternatively if those name fields are on the Customer table (not in a separate table) then you might want an #embedded. On the face of it you could just add the name fields as standard attributes to the Customer entity but it can be useful if those same columns appear on multiple tables (for example you might have the name columns on a Supplier table).
Its the difference between composition and aggregation. #Embedded objects are always managed within the lifecycle of their parents. If the parent is updated or deleted, they are updated or deleted as well. #OneToOne objects may mimic composition via the cascadeType option of their #Join annotation, but by default they are aggregated, aka their lifecycle is separate from that of their parent objects.
#Embedded is used with Value Objects (Objects which have a meaning only when attached to an Object) whereas one to one mapping is between two objects having their own existence and meaning.
For e.g.
Value Object and #Embedded: If we have a User class and this class has an address Object in it, it can be considered as a value object as the address alone does not have any significance until unless associated with a user. Here address object can be annotated with #Embedded.
One to One mapping and #OneToOne: If we have a User class and this class has a 'Father' Object or a 'Mother' object, we would want to annotate the 'Father' or 'Mother' instance as #OneToOne as 'Father' or 'Mother' have their own meaning and existence and are not Value objects to User class.
A closely related difference is between #OneToMany and #ElementCollection. Both are used to save instance variables of Collection type in Java class. The difference being, #ElementCollection is to be used when the elements of Collection being saved are Value Objects whereas #OneToMany is used when the elments and object have well defined meaning and existence.
Use #OneToOne, only if fields can be reused. Otherwise, go for #Embeddable.
A quote from Beginning Hibernte, 3rd Edition:
There is nothing intrinsically wrong with mapping a one-to-one association between two entities where one is not
a component of (i.e., embedded into) the other. The relationship is often somewhat suspect, however. You should
give some thought to using the embedded technique described previously before using the #OneToOne annotation.
#Embeddable:
If the fields in an entity (X) are contained within the same table as another entity (Y), then entity X is called "component" in hibernate terms or "embedded" in JPA terms. In any case, JPA or hibernate do not allow to use 2nd table to store such embedded entities.
Generally, we think of normalizing a table when data is being reused by more than one table. Example: A Customer (id, name, street, city, pin, landmark) can be normalized into Customer(id, name) and CustomerAddress(cust_id, street, city, pin, landmark). In this case, we can reuse CustomerAddress by linking the same using cust_id with other tables. But if this reuse is not required in your application, then we can just keep all columns in one table.
So, a thumb rule is,
If reuse -> #OneToOne,
If no reuse -> #Embeddable
#Embedded is typically to represent a composite primary key as an embeddable class:
#Entity
public class Project {
#EmbeddedId ProjectId id;
:
}
#Embeddable
Class ProjectId {
int departmentId;
long projectId;
}
The primary key fields are defined in an embeddable class. The entity contains a single primary key field that is annotated with #EmbeddedId and contains an instance of that embeddable class. When using this form a separate ID class is not defined because the embeddable class itself can represent complete primary key values.
#OneToOne is for mapping two DB tables that are related with a one to one relationship. #Id will be the primary key.
An application is developed with JSF and JPA.
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
Bill is the Parent class and subclassed to OpdBill, PharmacyBill, etc.
Multiple users may try to persist at the same time.
It is easy to generate sequence number for the Bill class, but that is not essential in the functionality.
How can we have separate auto-generated sequence numbers for sub classes? (not necessary the ID, just a serial number)
As far as i know JPA is not able to create such Sequences for non ID-Columns, but you could do some dirty workaround like this:
Generate a secound entity like
#Entity
public class OpdSequence {
#Id
#GeneratedValue
private Long id;
}
and create a 1-1 to your OpdBill
#Entity
public class OpdBill extends Bill {
#OneToOne
private OpdSequence opdId;
}
If OpdBill is a Bill, then both must share the same ID field, and Hibernate must be able to distinguish two bills (whatever their class is) thanks to their IDs. All the subclasses must thus share the same ID generation with the base class, and the IDs of all the instances of Bill and its subclasses must be unique.