這是一個相當長的(不是過於複雜的)設計問題,請耐心等待。我試圖通過POJO和JPA實施人員/角色管理系統。我對ORM相當陌生,這主要是映射問題。JPA/Hibernate的繼承映射
我已經得到了這個工作作爲POJO和我舒適與呼叫者級別的API,但現在想使用JPA將其映射到數據庫或在Seam環境中休眠。
我的實現基於Decorator(GoF)和Person Role Object模式(堡盟/ Riehle等人)。所有角色都是硬編碼的,並且不支持運行時添加新角色,因爲它需要更改代碼以擴展行爲。我會使用用戶組來實現安全性和權限。
有一個Person接口,包含諸如addRole(),removeRole(),hasRole(),getRole(),getRoles()等角色管理方法。具體實現由PersonImpl類提供。
有一個抽象類Role也實現了Person接口(用於裝飾器替代等價)以及一個擴展它的RoleImpl類。 Role類持有對個人實例的引用,用它來爲人員界面上的任何方法/屬性調用提供服務,這意味着Role的所有子類都可以處理Person接口。角色構造函數將person對象作爲參數。
這些是接口/類:
public interface Person {
public String getFirstName();
public void setFirstName(String firstName);
.
.
.
public boolean isEnabled();
public void setEnabled(boolean enabled);
public Set<Role> getRoles();
public Role addRole(Class<? extends Role> roleType);
public void removeRole(Class<? extends Role> roleType);
public boolean hasRole(Class<? extends Role> roleType);
public Role getRole(Class<? extends Role> roleType);
public enum Gender {MALE, FEMALE, UNKNOWN};
}
public class PersonImpl implements Person {
.
.
.
}
public abstract class Role implements Person {
protected PersonImpl person;
@Transient
protected abstract String getRoleName();
protected Role() {}
public Role(PersonImpl person) {
this.person = person;
}
public String getFirstName() {
return person.getFirstName();
}
public void setFirstName(String firstName) {
person.setFirstName(firstName);
}
public Set<Role> getRoles() {
return person.getRoles();
}
public Role addRole(Class<? extends Role> roleType) {
return person.addRole(roleType);
}
.
.
.
}
public abstract class RoleImpl extends Role {
private String roleName;
protected RoleImpl() {}
public RoleImpl(PersonImpl person) {
super(person);
}
.
.
.
}
public class Employee extends RoleImpl {
private Date joiningDate;
private Date leavingDate;
private double salary;
public Employee(PersonImpl person) {
super(person);
}
.
.
.
}
下圖顯示了類之間的關係:
(如果你無法看到圖在線,查看這裏via yUML)我想用這些類如下:
Person p = new Person("Doe", "John", Person.MALE, ...);
// assuming Employee extends Role
Employee e = (Employee)p.addRole(Employee.class);
由於角色類也實現了個人界面,我也可以這樣做:
// assuming Parent extends Role
Parent parent = new Parent((PersonImpl)p);
e.addRole(Parent.class);
e.getDateOfBirth(); // handled by the decorated person class
// assuming Manager extends Employee extends Role
Manager m = (Manager)p.getRole(Manager);
if (m.hasRole(Employee.class) {
// true since Manager derives from Employee
}
的問題,我有是:
(a)是本實施不必要的複雜性,如果這樣會怎樣是一個更簡單的方法?請注意,這進入了一個非平凡的業務應用程序,而不是一個kiddy項目,我認爲角色子類化對於員工,經理等情況下的行爲很重要。
(b)如何映射此在JPA /休眠?
(c)它可以被映射,所以我也可以利用Seam身份管理? (我的角色定義顯然不像Seam's)
(d)如果我使用每個子類的繼承類型(InheritanceType.JOINED)映射策略,我將PersonImpl映射爲PERSONS和RoleImpl作爲ROLES表,並映射RoleImpl的每個子類(如Employee和Parent)作爲EMPLOYEES和PARENTS自己的表。
我將不得不(對角色的集合中PersonImpl的)人員和角色之間的一個@ManyToMany關係,聯接表PERSON_ROLES。
現在的問題是,僱員和父母表等只有ROLE_ID引用,因爲繼承映射策略顯然認爲它們是角色(ROLES)的擴展,而我需要它們作爲PERSON_ROLES的附錄,並且需要USER_ID + ROLE_ID鍵被正確解析,或至少USER_ID。
我寧願一個規範化的數據庫,因爲它依賴於額外的連接而不是一個非規範化的數據庫,而這個數據庫很難維護並且可能會聚集大量未使用和不相關的字段,這就是爲什麼我認爲每個子類的表是要走的路。
或者在此場景中帶有鑑別器列OK(從數據庫維護角度看)的每個類的層次結構(InheritanceType.SINGLE_TABLE)?請注意,某些角色可能會有幾十個屬性/字段。 (e)這種設計有更好的選擇嗎?
非常感謝任何想法/建議。
如果每個角色對象都適用於單人對象,如代碼所示,那麼爲什麼人和角色之間存在@ManyToMany關係?是不是@OneToMany? – 2010-07-18 18:28:16
一個人可能有多個角色。每個角色可能有多個人。我認爲亞瑟在@OneToMany的一面和@ManyToOne在另一面的觀點可能有一些優點。必須檢查... – 2010-07-19 06:28:41