1

So let's say you have

class Employee {
 @ManyToOne
 @JoinColumn
 private Department department;
}

class Department {


}

class EmployeeGroup {

   @OneToMany
   @JoinTable
   private Set<Employee> employees;

   @ManyToOne
   @JoinColumn
   private Department department;
}

How would you ensure that all employees from a specific group, are from the same Department as the EmployeeGroup's department ?

I've tried with array of @JoinColumn within @JoinTable... but It seems that hibernate can't share in link table the same column for fk_department_id in both Foreign keys.

What I expect to get is : a link table with three columns, fk_group_id, fk_employee_id, fk_department_id, and 2 FK (department_id, employee_Id) to employee table, and (department_id, group_id) to emp_group table.

Is it possible without ComplexPK?

Business case : you have two departments, IT and Finance, 3 groups, Java Group and .NET group which belong to IT department, HR group which belong to Finance department. You have 5 employees. all of them are in IT department, two of them also in Java group, two of them in .NET group, and one of them is an internship member which does not belong to any groups yet, but it is in the same department. Now I want to ensure that when you take 1 employee from IT department and say employee.getGroups(), all of them are also IT groups and the collection does not contain accidentally the HR group.

Andrei Amarfii
  • 685
  • 1
  • 6
  • 17
  • Why would you want to ensure it on the database mapping level? That's a business rule that `EmployeeGroup` should be validated against before you try to persist anything – crizzis Dec 22 '17 at 14:01
  • I wouldn't want to end up with incorrect mapping in DB. `EmployeeGroup` is a group of `Employee`s within one `Department` – Andrei Amarfii Dec 22 '17 at 14:04
  • This is perfectly possible in SQL. You have a linked Table with two FK with two columns each. This may require you to have Unique Keys in both Employee(id, department_id) and EmployeeGroup(id, department_id), but I just try to figure out how to represent this in JPA. – Andrei Amarfii Dec 22 '17 at 14:12
  • I never said it was impossible, just that it wasn't a good idea. Your schema is redundant, in that the employee's department information is duplicated, since it is present in both the link table and the employee table. – crizzis Dec 22 '17 at 14:22
  • @crizzis you may sometimes work with a legacy database! – O.Badr Dec 29 '17 at 09:15
  • @O.Bard Fair enough, but the question asked was 'how would you ensure that all employees from a specific group, are from the same Department as the EmployeeGroup's department?' and not 'how do I map this legacy db schema?' – crizzis Dec 29 '17 at 10:31
  • Why would you think that this is a legacy db schema ? how would you build the tables then ? The use case is simple...you have a lot of employees they are mandatory in one department...but they also can be optionally in a lot of groups within the same department.... – Andrei Amarfii Dec 30 '17 at 07:59

3 Answers3

1

How would you ensure that all employees from a specific group, are from the same Department as the EmployeeGroup's department?

If you want to make this restriction in Hibernate/JPA level which is also the DB level you need to make this restriction with a composite primary key, the primary key will hold both the DepartmentPK and the EmployeeGroupPK for every Employee.

is it possible without ComplexPK?

The short answer is No, because only a composite primary key can provide these restrictions on all sides foreach Employee.

Otherwise you will keep your mapping as it is and make these restrictions in the business level.

cнŝdk
  • 31,391
  • 7
  • 56
  • 78
0

In this particular scenario why are you making relationship between employee and department classes?(I don't think it is a well normalized design too)

Why don't you just specify the below mentioned relations: 1. One To Many relation in EmployeeGroup with Employeee 2. Many To One relation in EmployeeGroup with Department 3. Many To One relation in Employee with EmployeeGroup 4. One To Many relation in Department with EmployeeGroup

In this way, you can derive the department of an employee via its employee group and make sure that employees belonging to same employee group belong to same department.

codeLover
  • 2,571
  • 1
  • 11
  • 27
  • The use case is simple...you have a lot of employees they are mandatory in one department...but they also can be optionally in a lot of groups within the same department.... – Andrei Amarfii Dec 30 '17 at 15:18
  • 1
    So when the employee is not in any groups, how would you guess the department ? – Andrei Amarfii Dec 30 '17 at 15:18
  • Business case : you have two departments, IT and Finance, 3 groups, Java Group and .NET group which belong to IT department, HR group which belong to Finance department. You have 5 employees. all of them are in IT department, two of them also in Java group, two of them in .NET group, and one of them is an internship member which does not belong to any groups yet, but it is in the same department. Now I want to ensure that when you take 1 employee from IT department and say employee.getGroups(), all of them are also IT groups and the collection does not contain accidentally the HR group. – Andrei Amarfii Dec 30 '17 at 15:23
  • " one of them is an internship member which does not belong to any groups yet, but it is in the same department. " For this scenario you can easily handle by adding a group Intern IT(though it is not one of the groups of your business scenario) with department as IT. See it is the technical implementation and it depends completely on developer how to proceed with the implementation. . – codeLover Jan 01 '18 at 04:48
0

How would you ensure that all employees from a specific group, are from the same Department as the EmployeeGroup's department?

You can ensure that by making a relation between Employee and EmployeeGroup which has an association with Department and remove Department<-->Employee association, so to know which Department an Employee belongs to, you should navigate through EmplpoyeeGroup association.

So when the employee is not in any groups, how would you guess the department?

You can solve this by using a default group for each Department, so every Employee that is not affected to a group, must belong to his Department's default group, so your mapping will be :

public class Employee{    
    @ManyToOne(optional = false)
    @JoinColumn(name = "EmployeeGroup_id")
    private EmployeeGroup employeeGroup; 

    ...
}

public class Department{
    @OneToMany(mappedBy = "department")
    private List<EmployeeGroup> employeeGroup;        

    @OneToOne(optional = false, orphanRemoval = true, cascade = CascadeType.ALL)
    @JoinColumn(name = "DefaultEmployeeGroup_id")
    private EmployeeGroup defaultEmployeeGroup;

    ...
}

class EmployeeGroup {

    @OneToMany(mappedBy = "employeeGroup")
    private Set<Employee> employees;

    @ManyToOne(optional = false)
    @JoinColumn(name ="department"_id)
    private Department department;

    ...
}

This solution may remove a redundant association between Employee and Department and will enforce the business rule on the database side.

The Second solution:

Is checking integrity between Employee's group and his Department in your code, by checking the setDepartment(Department) and setEmployeeGroup(EmployeeGroup) in your Employee class. Here the business rule won't be checked in the database layer (if other application uses the same database).

Note:

  • I don't prefer a composite primary key for sake of simplicity unless I don't have a choice.
  • I don't think it's a good idea to use @JoinTable with @OneToMany for EmployeeGroup.employees field, Hibernate will create a separate table for EmployeeGroup-->Employee association.

Hope it helps.

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
O.Badr
  • 2,853
  • 2
  • 27
  • 36