Suppose we have two database tables Instructor and Instructor_Details. They have one to one relationship such that each instructor can have one instructor detail and one instructor detail is associated with one instructor only.
In pure database terms, Instructor table should be the parent of Instructor_Details table and the primary key of Instructor table should be used as foreign key in Instructor_Details table.
I was learning Hibernate and most of the examples of #OneToOne on internet have modified the tables such that the Instructor_Details primary key is used as foreign key in Instructor table, which seems contradictory as Instructor should be the parent of Instructor_Details.
How can i implement both entities in best way such that i can use the primary key of Instructor as foreign key in Instructor_Details. Also please explain the fetch types and cascade in my desired implementation. Examples with code will be very helpful.
Edit
Let us say the attributes for the tables are as follows:
Instructor(instructor_id (primary key), first_name, last_name)
Instructor_Details(detail_id (primary key), dob, address, instructor_id (foreign key from instructor table))
Since in pure database terms you're modeling this as parent/child you're stuck with OneToMany. What I've done in this situation, so I can keep the relationship like that and take advantage of things like on cascade delete, etc. Is to have helper methods on the entities themselves. Since Hibernate uses reflection you don't actually need to implement public getters and setters to your private members.
So for example your accessor for InstructorDetails Instructor class can look like:
public class Instructor {
...
#OneToMany
private List<InstructorDetails> instructorDetails;
public Optional<InstructorDetails> getInstructorDetails() {
if (instructorDetails == null || instructorDetails.size() == 0) {
return Optional.empty();
} else if (instructorDetails.size() > 1) {
// Optional raise if you want to be aware of corrupt Instructors that have many details
throw Exception("There's corrupt data");
} else {
return Optional.of(instructorDetails.get(0));
}
}
...
}
Makes sense? Same for add ... you can have an add that takes a single detail, checks if there's one already and overwrites or throws, but internally it deals with the list. Whoever deals with Instructor will never know there's a list holding them inside.
Related
I don't have a lot of experience with database design and i try to understand the general logic behind it with using an ORM like hibernate. I have two tables user and languages. User could know one or more languages so there is a one to many relation between two tables. But i have a fixed length of languages English , Spanish and French for example. As i understand with each new user instance persisted there will be duplicate entries in the language table with a foreign key of that person. Is there a way to prevent this duplicate entries ?
Your understanding is a little confused. You can map a OneToMany relationship using a Foreign Key, and there are good database reasons to do so, though generally a JPA provider recommends against it. However, you are describing a ManyToMany relationship. A User will (or could) have many Languages. A Language will have many Users. When you create a many to many relationship with annotations:
#Entity
public class Person {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToMany
private List<Language> languages;
and
#Entity
public class Language {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
The JPA provider will create an association or Join Table, with an id from each Entity in it:
create table Person_Language (Person_id bigint not null, languages_id bigint not null)
When you create a language, an entry will be put in the language table. When you create a user, an entry will be put into the user table. When you add a language to a person's languages then an entry will be put into the Join Table.
insert into Person_Language (Person_id, languages_id) values (?, ?)
There will be only unique combinations of Person_id and languages_id in the join table, and so the database will be well normalized. You would not be able to assign a language to multiple users using a Foreign Key in the Language entity for the reason you pointed out: there would be only one foreign key column for any given language.
For example I have two entities : Enterprise, Department. Enterprise has many departments, department has one enterprise, so there is a column - Enterprise_ID in Department table.
I have a function for saving Department object
void save(Department department);
To add Enterprise_ID in the table I need to have either reference on Enterprise object or enterprise's id.
Which way is more suitable?
However I prefer do not have such information in department object but on this way how can I save Enterprise_ID in the table ? It seems to me Hibernate somehow doing it.
public class Department{
private long id;
private String name;
private DepartmentType type;
private List<Employee> employees;
//getters()/setters()
}
public class Enterprise{
...
private List<Department> departments;
...
}
Department does not have any information about Enterprise in which it exists. So using only department object I can't insert Enterprise_ID(FK) in department table. But hibernate's save method somehow doing it. How can I do it without hibernate using entities above;
I use JDBC.
To do it the same way as hibernate does, you would have a save(Enterprise) method that would persist the enterprise object to the db and also insert/update the foreign key association.
Hibernate supports both nullable and non-nullable foreign key. In the latter case, it will first insert the enterprise, obtaining its primary key value, and then insert the department's along with the correct foreign key value.
You could do the same. But the save(Department) method would only be able to do updates on the department table and not change the association to the enterprise table. To do that, you would have to change the collection in enterprise and save/update that to the db.
Hibernate will only save/update the foreign key if you change something in the Enterprise.departments collection. It's the only way to do it if you don't have the reverse relation.
In your code, you'll have to use the Enterprise object to update the foreign keys in the Department table.
You could create a bidirectional association, by putting a field 'enterprise' in your Department class, but then you need to keep both relations in synch manually...
I don't really know how to describe this problem (as you tell by the dodgy title), so here's a full description of the problem.
I have two classes, Teacher and Class.
Each teacher can teach to several classes and each class has several teachers.
In Java, we've mapped it like this:
public class Class {
#ManyToMany(mappedBy = "classes")
private List<Teacher> teachers = new ArrayList<>();
}
We have a superclass, User, and two subclasses, Teacher and Student. These classes inherit from the User superclass. So, in our database we have a table called Users which stores all users as teachers or students.
Now, students can only be in one class, so they can only have one ClassID stored in the database.
But as I said before, teachers can have several classes. So the point is : How am I able to store all the classes that a teacher has in the database?
I see Java created an extra table, called User_Class, which is probably ment to store all the different classes a teacher has and vica versa. Problem is that I can't find any documentation about how to work with this.
Can someone please give me a hand here?
Thanks in advance.
Before trying to solve this by code, I think you need to understand it from the database point of view.
You are trying to build a many-to-many relationship. This sort of relationship is built by splitting it in two one-to-many relationships.
So, if you have two entities (namely Course and Teacher... I avoid using "classes" to prevent confusion), and one Course can have many Teachers and one Teacher can have many Courses, then a way to create the relation (in the database) would be like this:
Table Courses
courseId (PK)
courseName
Table Teachers
teacherId (PK)
teacherName
Table Courses_Teachers
courseId (FK, PK)
teacherId (FK, PK)
(PK stands for "primary key", and FK stands for "foreign key")
Hope this little introduction helps you visualize the way to solve your problem.
That approach is based on a composite primary key.
This link is about that:
how to make a composite primary key (java persistence annotation)
I know that this can be easily solved with an HQL query, however I prefered to simply have Hibernate handle this with a few OneToMany properties for me.
Let me demonstrate what I want my domain model to look like in pseudo-code:
Game
Long GameID
Team HomeTeam
Team AwayTeam
#OneToMany(mappedBy="team")
Set<TeamPlay> HomeTeamPlays
#OneToMany(mappedBy="team")
Set<TeamPlay> AwayTeamPlays
The table structure is similar, there are two foreign keys that both point to the Team table on the Game table. Clearly if there were only one foreign key then it would represent a true One-To-Many relationship but in reality what I want is two bi-directional One-To-Many properies for the same entity child type.
I don't believe using the #Where annotation will work as it requires a constant, and #JoinColumn is not allowed here. If it is not possible then that is okay, I just wanted to here it from somebody else.
I bet you don't really understand the use of mappedBy.
You may refer to my other answer in https://stackoverflow.com/a/13812047/395202
In short, mappedBy is the property name in the "opposite side" of a bi-directional relationships.
For you case, it probably look something like:
class TeamPlay {
#ManyToOne
Team homeTeam;
#ManyToOne
Team awayTeam;
}
class Team {
#OneToMany(mappedBy="homeTeam")
Set<TeamPlay> homeTeamPlays;
#OneToMany(mappedBy="awayTeam")
Set<TeamPlay> awayTeamPlays;
}
There is nothing wrong with your code. I've tested it with #ManyToOne on TeamPlay class and it works fine. Creates a join column on TeamPlay table as expected. Nothing unusual
I have 2 entities: Class(of students) and Student. A student can be in many classes(like in college) and a class has many students. The problem is how to ensure that this entity, generated in the middle, has 2 primary keys, the ids of each other entity (Student and Class).
I need to know how to create it using annotations. I use EJB3 and JPA Annotations in the project.
First, you don't need a middle entity. You have two entities and a join table between them.
You need a middle entity only if you have additional information about the relation - for example a StudentClass may have timesAbsent column.
In case you really need the third entity, you can have:
an #EmbeddedId, where you define a separate class holding the two parts of the primary key. That class must be #Embeddable
an #IdClass which will let you specify two #Id fields. You'll again need another class to hold the two fields representing the key.
See this question for which option to choose.
Note that you thus have a composite primary key, not two primary keys (which you can't have)
I know how to make this happen using hibernate. May be it'll help.
Make the collection type Set.
public class CollegeClass {
private Set<Student> students;
}
public class Student {
private Set<CollegeClass> classes;
}