7

Here is parent class Enterprise. It has employers and one of them is president of enterprise.

@Entity
class Enterprise
{
   // fields

   @OneToMany
   public List<Employee> getEmployers()
   // implementation    

   @OneToOne
   public Employee getPresident()
   // implementation

}

Here is child Employee class. It has only info about Enterprise where he works. But question is what association should I use?

@Entity
class Employee 
{
   // fields

   // what association should I use?
   public Enterprise getEnterprise()
   // implementation
}
Artyom Chernetsov
  • 1,394
  • 4
  • 17
  • 34

3 Answers3

7

Given that you've defined the Enterprise->Employers association with @OneToMany, which means that an Employer belongs to only one Enterprise, you should be using @ManyToOne, meaning that every Employer belongs to max. 1 Enterprise, but an Enterprise can reference many Employers.

You can define the association specifics (join columns, etc) in one of the sides only, using the mapped-by attribute in the annotation:

@Entity
class Enterprise
{
   @OneToMany(mapped-by="enterprise")
   public List<Employee> getEmployers()
   // implementation    

   @OneToOne
   public Employee getPresident()
   // implementation
}

@Entity
class Employee 
{
   @ManyToOne
   @JoinTable ( name="Enterprise", joinColumns={ @JoinColumn(name="ENT_ID", referencedColumnName="ENT_ID") }
   public Enterprise getEnterprise()
   // implementation
}

In case an Employer could be president of a different Enterprise in which he is employed (seems unlikely, unless one can be president of an enterprise without being employed by it), and in case you needed to access the Enterprise of which the Employer is president from the Employer entity, you would need to add another association, ideally with @OneToOne (you would encounter problems, because @OneToOne relations require both entities to have the same @Id class). In this case I would annotate the getPresidedEnterprise() method on Employer with @ManyToOne for practical reasons.

Xavi López
  • 27,550
  • 11
  • 97
  • 161
  • but what about President field? I should use OneToOne association, but employee.enterprise annotated with ManyToOne... – Artyom Chernetsov Oct 04 '11 at 12:12
  • 1
    @Artyom - They are not connected. There won't be a problem. The president is a different column. – Petar Minchev Oct 04 '11 at 12:14
  • 1
    It would only be a problem in case an Employer could be President of a different enterprise in which he is employed. Only then, and in case you nedd to access the Enterprise of which the Employer is president from the Employer entity, you would need to add another association, ideally with @OneToOne (you would encounter problems, because `@OneToOne` relations require both entities to have the same `@Id` class). – Xavi López Oct 04 '11 at 12:15
  • Is it right that in this case getEmployers is bidirectional association and getPresident is unidirectional? – Artyom Chernetsov Oct 04 '11 at 12:26
  • 1
    Indeed, getEmployers is bidirectional because you can get Employers from Enterprise and Enterprise from Employers (normal employers). If the president of an enterprise has to be employed in the same enterprise he presides, then you could say that getPresident is bidirectional too. If not, it would be unidirectional, because you can't get the Enterprise a president presides from the Employer entity. – Xavi López Oct 04 '11 at 12:29
  • It's first case (president of an enterprise has to be employed in the same enterprise he presides). So looks like it should be defined as alh84001 says: add field getEnterpriseWhereImPresident annotated as OneToOne. But I may be wrong – Artyom Chernetsov Oct 04 '11 at 12:36
  • 1
    As I said in my comments and in my edit in the answer before, you **can** use a `@OneToOne` in case the classes of the `@Id`'s of `Employer` and `Enterprise` are the same. – Xavi López Oct 04 '11 at 12:39
  • And, if the president is employed by the same Enterprise in which he is employed, the `@OneToOne` will be unnecessary, because it will always associate to the same entity `getEnterprise()` is already associated to. – Xavi López Oct 04 '11 at 12:49
1

Use @ManyToOne annotation. It is the opposite side of a one-to-many relation. It says an employee can have one enterprise, but an enterprise can have many employees.

Petar Minchev
  • 46,889
  • 11
  • 103
  • 119
1

You should have two properties on the Employee class. Employee table should have a reference to an enterprise, ad enterprise should have a reference to an employee-president.

(you could also probably subclass an Employee based on the isPresident flag column, but I don't have experience with that)

@Entity    
class Enterprise    
{    
    // fields

    @OneToMany(mappedBy="enterprise")    
    public List<Employee> getEmployees(){} 

    @OneToOne
    @JoinColumn(name="PRESIDENT_ID")
    public Employee getPresident(){}
}    

@Entity 
class Employee  
{ 
    // fields

    @ManyToOne
    @JoinColumn(name="ENTERPRISE_ID")
    public Enterprise getEnterprise(){}

    @OneToOne(mappedBy="President")
    public Enterprise getMyEnterprise(){}
} 
alh84001
  • 1,263
  • 1
  • 15
  • 25
  • But what is the meaning of field getMyEnterprise for not-president employers? Will it return null value? – Artyom Chernetsov Oct 04 '11 at 12:31
  • The `@OneToOne` mapping would not work in all circumstances, at least in Hibernate, because `Employer` and `Enterprise`'s `@Id` mappings would be expected to be of the same type. – Xavi López Oct 04 '11 at 12:35
  • It _should_ return null :). Or you could just make the relationship unidirectional. Also, consider what Xavi stated about id types. – alh84001 Oct 04 '11 at 14:50