hezus
hezus

Reputation: 25

Parent - Child relationship - self join mapping

I'm trying to build an application which will receive the XML file with list of Employees and store the parent-child/employee-manager relation in the single database table.

My XML file looks like this one:

<Employees>
    <Employee manager="Patrick">Martin</Employee>
    <Employee manager="Patrick">Kent</Employee>
    <Employee manager="Martin">Mark</Employee>
    <Employee>Hugo</Employee> <!-- root element of the employee-manager tree -->
    <Employee manager="Hugo">Osa</Employee>
    <Employee manager="Osa">Patrick</Employee>
</Employee>

One employee can have only one manager, but one manager can have multiple subordinates/employees.

I have no troubles when unmarshalling the received XML file but now I'm trying to create the appropriate model which will allow me to store the unmarshalled values in the database. Data should be stored in the table named "Employee" and should contain following data:

------------------------------
| id            | Integer    |
------------------------------
| employee_name | String     |
------------------------------
| parent_id     | Integer    | -- reference to the manager
------------------------------

I created a new class named Employee but I'm not sure how to define appropriate ManyToOne/OneToMany annotations.

Since I'm fairly new to this, I've Googled couple of examples and tutorials (as well as the answers on the similar questions here on Stack Overflow), but I guess I'm making some big mistake in this implementation when defining this model. My latest try looks like this:

public class Employee {
    @Id
    @GeneratedValue
    private int id;

    @Column(name = "parent_id")
    @Transient
    @ManyToOne(cascade={CascadeType.ALL})
    private String managerName;

    @Column(name = "employee_name")
    @JoinColumn(name="parent_id")
    private String employeeName;

    // getters and setters

If anyone could point me in the the direction of defining appropriate model, it would be much, much appreciated!

Upvotes: 1

Views: 3999

Answers (2)

Bartha Barna
Bartha Barna

Reputation: 24

You should simply have a ManyToOne relation to your Employee table, that is several employees can have the same manager (who is also an employee) and for the manager this field will remain empty, like this:

@Entity
@Table(name = "EMPLOYEE")
public class Employee {

    @Id
    @GeneratedValue
    private int id;

    @ManyToOne
    private Employee manager;

    @Column(name = "employee_name")
    private String employeeName;

Upvotes: -1

cнŝdk
cнŝdk

Reputation: 32175

In Hibernate when you want to map a ManyToOne relationship you map it between entities and not just properties, so you need to reference an object of type Employee and not only a String or an id.

Problems:

  • So your mapping is incorrect and will throw many mapping errors, instead of writing:

    @Column(name = "parent_id")
    @Transient
    @ManyToOne(cascade={CascadeType.ALL})
    private String managerName;
    

    You need to map the ManyToOne realtionship like this:

    @ManyToOne(cascade={CascadeType.ALL})
    @JoinColumn(name="manager_id")
    private Employee manager;
    
  • And make sure you map the other side of the relationship like this:

    @OneToMany(mappedBy="manager")
    private Set<Employee> subordinates = new HashSet<Employee>();
    
  • Also your mapping for the column employee_name is incorrect, the @JoinColumn is only used for relationships and can't be used with a simple column, you need to write it like this:

    @Column(name = "employee_name")
    private String employeeName;
    
  • The @Transient is useless in your mapping, we only use it if we want to use an attribute that won't be persisted in the database.

  • And most important make sure you map your class with @Entity, so it can be persisted in the database.

Example:

You can check Hibernate Self Join Annotations One To Many mapping example it uses the same model you want to implement.

Upvotes: 2

Related Questions