views:

80

answers:

2

Hi, I'm not 100% sure this is only a Hibernate issue as this might be a more abstract decision but I'll give it a try.
Since the problem description is a bit lengthy I'll first state that what I'd like to do is see if I can change the implementation to something which more resembles a Best practice implementation then this.

I have 3 entities, relevant to this issue: Workstation (ws), Employee and Organization-unit(org-unit).
An Employee can belong to one org-unit.
An Org-unit can hold many employees.
A Workstation is used to display data of an Org-unit(in general), Of an Org-unit and a specific employee in it and an employee which does not belong to an org-unit.

Currently, for various reasons which were out of my control, we do not use any associations between the entities in Hibernate or via DB-Constraints but we just use Columns which logically serve as Foreign-Keys.
We currently have an additional table which has 4 columns:Id,WSId,EmployeeId,OrgUnitId.
This allows a WS to refer to an orgunit (where employeeId is null),to an employee without an org-unit (orgunitId is null) or to an employee and org-unit (where none are null).

I'd like to be able to know:
1.Given a WS, which employees is it following and which org-units and how (i.e., alone, with an employee? which?)
2.Given an employee, which WS are monitoring it.
3.Given an org-unit, which WS are monitoring it and how (i.e., alone, with an employee? which?)
This issues relates to the Presentation layer as it dictates the view will be generated BUT it is a part of the domain model as a user, will use, an interface to manipulate these monitoring mappings and so these mappings are a part of the domain model.

I'm not sure if what I have is not the least evil among options, and I would greatly appreciate comments and suggestions.

EDIT From one of the answers I think it is not clear enough that a WS can display data for many such mappings at the same time, in a mixture of the above sorts (org-unit, employee etc.)

A: 

Sounds like all you really need is a nullable FK on Employee to OrgUnit, and two nullable FKs on WS to both Employee and OrgUnit. To see which WS are monitoring an employee, just get all the WS with matching emp_id columns. Same with the WS monitoring an OrgUnit, possibly with the additional stipulation of emp_id being null or not (depending on if you need to handle those situations separately). No idea where "patients" fits in, you didn't give any details about that.

TMN
@TMN, Sorry about the 'patients', I was distracted when I added that line, it's supposed to be employees. I've corrected the question. I also added an update to an issue which I think you missed as your solution ignores the fact that a WS can monitor many such mappings. Thanks.
Ittai
In that case, you probably already have the proper solution. Possible changes would be to remove the artificial "id" field and just have a three-part primary key (which happens to be the whole record), or to split that table up into separate WS->Emp and WS->OrgUnit mappings, but I don't know that those are really improvements (unless the association table is going to be really large, in which case it may make administration easier if you split it up).
TMN
Oops, forgot this was in Hibernate, so you'll want to keep the artificial ID.
TMN
A: 

OK, I don't know how to implement this on the database side, but here is an Entity Model that should cover the relationship you are talking about.

Edit: This is a new version in response to your comments. Now every WorkStation has n bindings each of which can have employee or orgunit or both (use DB constraints to ensure they don't have neither).

You can also access the bindings per orgunit and per employee, which should make the above queries much easier:

@Entity
public class OrgUnit{

    @OneToMany(mappedBy="orgUnit")
    private Set<Binding> bindings;

}

@Entity
public class Employee{

    @OneToMany(mappedBy="employee")
    private Set<Binding> bindings;

}

@Entity
public class Binding{

    @ManyToOne(optional = true)
    private Employee employee;

    @ManyToOne(optional=true)
    private OrgUnit orgUnit;

    @ManyToOne(optional=false)
    private WorkStation owner;

}

@Entity
public class WorkStation{

    @OneToMany(mappedBy="owner")
    private Set<Binding> bindings;

}

Sample Client code:

public Set<WorkStation> getWorkstationsPerEmployee(final Employee employee){
    final Set<WorkStation> workStations = new HashSet<WorkStation>();
    for(final Binding binding : employee.getBindings()){
        WorkStation workStation = binding.getOwner();
        if(workStation!=null)
            workStations.add(workStation);
    }
    return workStations;
}
seanizer
@seanizer, Thanks for your reply. I'm not sure what the @OneToOne mappings of a WS mean in org-unit/employee as a single org-unit/employee can be monitored by many WS at the same time.Also, your `WorkstationEmployeeBinding` is something I thought of but if you add my input from the begining of the comment you'll see that I'll need also `WorkstationOrgUnitBinding` and `OrgUnitEmployeeBinding` to reflect all the many to many. All these additional dummy classes don't feel like the right direction, but I might be mistaken. Thanks.
Ittai
@Ittai OK, now here's a much simpler but more flexible solution with only one binding class
seanizer
@seanizer, thanks for your solution. I was hoping for an "in-house" solution of hibernate but I guess this will have to do. Thanks again
Ittai