2009-12-08 26 views
1

我是新手。我正在編寫一個連接到Oracle 9i數據庫的Java應用程序。我需要強制執行我的應用程序像一些規則:通過編程寫入觸發器或執行操作?

委員會的主席必須添加/刪除,成員在委員會B.

有需要被執行大約10這樣的規則。我處於一個兩難的境地,無論是通過編寫觸發器還是通過編程在我的應用程序中來實施這些規則。

我欣賞任何建議。

感謝,

回答

3

我可能是錯的,但你說的是像一個實際的業務規則的聲音是什麼(Comittee A的主席必須是B的成員,或者不能爲B的成員)。國際海事組織,這應該由應用程序而不是數據庫來處理。

+0

+1在代碼中的業務邏輯。就我個人而言,我認爲觸發器對絕大多數目的都是邪惡的。 – 2009-12-08 16:09:34

+1

@戴夫Swersky:我們使用觸發器來保持在一個非常重要的數據錄入應用程序(因此所有數據項發生變化輸入到數據庫表)的審計線索,這就是它。所有這些觸發器都在做,雖然,在一個表中插入記錄(指示值changea和操作的類型,以及偵探小說)。我肯定不希望我的觸發器改變其他表中的數據。 – peacedog 2009-12-08 16:15:34

1

專門解決數據完整性的規則在數據庫中得到執行。規則是更合乎邏輯/業務規則,我不認爲屬於在數據庫,因爲

  • 他們是不可見的應用程序代碼
  • 他們更可能是可變的,而這會帶來不便如果他們被烘烤到數據庫。

我更希望看到數據庫強制執行的事情類型是「委員會記錄名稱不能爲空」,即數據完整性所必需的事情。

0

假設這些規則與有關組織的政策相關 - 即「所有委員會主席必須是至少一個其他委員會的成員」或「沒有委員會必須少於兩名成員」,那麼您應該可能把它們放在Java中。 Java是比SQL和RDBMS更靈活的編程環境。

說你的規則是「沒有委員會主席可以成爲任何其他委員會的成員」。你可能會實現這樣的:

public class Committee { 

    private Person chairman; 
    private Set<Person> members; 

    public Person getChairman() { 
     return chairman; 
    } 

    public void setChairman(Person person) { 
     for (Committee other : person.getMemberships() { 
      other.removeMember(person); 
     } 
     chairman = person; 
     addMember(person); 
    } 

    public void addMember(Person person) { 
     members.add(person); 
     person.addMembership(this); 
    } 

    public void removeMember(Person person) { 
     members.remove(person); 
     person.removeMembership(this); 
    } 

    public Set<Person> getMembers() { 
     return new HashSet<Person>(members); 
    } 
} 

public class Person { 

    private Set<Committee> memberships = new HashSet<Committee>(); 

    public Set<Committee> getMemberships() { 
     return new HashSet<Committee>(memberships); // Return a copy, not the original 
    } 

    public void addMembership(Committee committee) { 
     memberships.add(committee); 
    } 

    public void removeMembership(Committee committee) { 
     memberships.remove(committee); 
    } 

} 

然後,您可以編寫單元測試委員會確認爲主席的規則工作,他們會跑得很快,因爲他們不會需要數據庫。

public class CommitteeTest { 

    @Test 
    public void testChairmanship() { 

     // Set up the initial conditions 
     Person person = new Person(); 
     Committee other = new Committee(); 
     Commiteee commitee = new Committee(); 
     other.addMember(person); 

     committee.setChairman(person); 
     assertTrue(committee.getChairman().equals(person)); 
     assertFalse(other.getMembers().contains(person)); 
    } 
} 

(您可能想使用一個模擬對象的人,因爲這個單元測試應該僅測試委員會)

當您添加更多的規則,你將增加更多的單元測試,那麼會繼續快速運行。

+0

記住,這些「強制執行」如果有多人同時工作經常中斷。例如,某人在與其他人同時向某個委員會加入人員使他們擔任主席的情況下。要真正實施這些規則的唯一方法是序列化操作,以便在確定測試期間狀態是否固定的情況下完成任何驗證測試。 – 2009-12-10 22:19:20

2

我認爲如果一個約束可以在數據庫中執行,那麼它應該是,但是應用程序應該嘗試首先執行它,並且數據庫應該只作爲備份來使用 - 故障安全,if你喜歡。

但是在RDBMS中有一些難以實施的限制,這個例子就是其中之一。這很難,因爲數據庫的本地約束類型(獨特的,檢查,引用等)不允許你強制執行它,你將不得不恢復到觸發器或物化視圖等等。觸發器是在強制約束可怕,因爲查詢的隔離級別可能會導致一些違反打滑,而且他們也無法讀取或修改受影響的表(變異表的問題)。

是公平的,雖然應用程序級的約束檢查從查詢隔離級別,因此,使用的數據庫約束作爲備份同樣的問題困擾。

+0

我同意。任何業務規則應該儘可能低。如果您在數據庫中執行業務規則,那麼當您重新編寫客戶端或編寫額外的iPhone Widget時,業務規則仍然存在。但是,如果您發現自己在非正常的環境中跳躍以使觸發器執行您的業務規則,那麼不要擔心它太多 - 它可能只是應用程序級別的業務規則。 – 2009-12-10 23:00:08