2010-09-02 57 views
7

最近我一直在想。假設我們正在用JSF + Spring + JPA/Hibernate(或者其他任何技術)做web應用程序,並假設我們有一個「User」實體。我們希望用戶擁有唯一的登錄名。如果我們想這樣做,那麼我們可以在「登錄」列上放置一個@UniqueConstraint,但是我們的應用程序仍然需要在用戶註冊期間檢查用戶輸入是否有效(唯一),沒有這個輸入並且只有DB約束我們只會得到一個錯誤。這讓我想到,數據庫約束是否真的有必要/有幫助?只有當我們能夠給他們帶來任何好處時,我纔會想到他們會有人試圖破解我們(但我猜我們的應用程序應該是SQL注入證明),或者我們嘗試手動更改數據庫內容(不應該真的發生)。事實上,現在我想到了,一般必要/良好實踐中的數據庫約束?像繩子等對DB有獨特的限制嗎?

+0

有沒有人真的認爲在一個攻擊必須通過一個特定的不同的載體第一個假設下留下一個攻擊矢量是否可以開放?還是有人寫這樣的文章是爲了挑釁和激發討論? – bbadour 2010-09-03 13:48:36

回答

8

對於我來說,斷然是,從97看到Database as a Fotress丹澤的lenght思軟件架構師應該知道。他說比我好得多。

+0

真的很喜歡這個鏈接,謝謝! – 2010-09-02 15:38:30

+0

雖然所有的文章都是*開放源代碼*,所以你可以在wiki上免費閱讀它們 – 2010-09-02 15:41:44

4

是的,他們是。他們在最低級別執行數據完整性。

您可能需要手動更改數據庫的內容(即升級到新的版本)

你可能會忘記檢查你的代碼中的一些限制。

你可以看看這個像客戶端/服務器驗證。你的程序是客戶端,db是服務器。大多數情況下,客戶端驗證就足夠了,但是您必須進行服務器驗證,以防出現問題。

3

我認爲一個數據人會說這兩個都是絕對必要的。您的問題假設您的中間層應用程序代碼將永久存在於該數據庫的前面。

事實是,中間層應用程序來來去去,但數據永遠存在。

在模式設計中,沒有遠離列的長度。我想你在問中層是否是強制執行它們的好習慣。也許不是,但它們是數據庫的關鍵。

1

通常,當您聲明一組列是唯一的時,它就是您想要查詢的內容 - 因此無論如何它應該最有可能被編入索引。

是的,你的應用程序應該做適當的檢查,但是如果錯誤發生了,該怎麼辦?如果你的數據庫知道一些東西是唯一的,至少你知道你不會存儲無效數據(或者不是非常「無效」的數據,比如重複的數據是唯一的)。無論如何,你可以提出相反的問題:你花費什麼?

0

約束,無論是獨特的還是外來的,不僅強制數據完整性,而且它們具有性能影響。在沒有這些「非正式」常量的知識的情況下,數據庫優化器將對如何執行語句做出不可預知的決定。

1

如果你想要有不好的數據,那麼取消數據庫中的唯一約束。自從20世紀70年代以來,我一直在處理數據庫,並且查詢或導入了存儲在數百個數據庫中的數據。我從來沒有在數據庫中看到在應用程序級別設置不當的數據。除應用程序之外,許多其他應用程序都會觸發數據庫(從其他系統導入數據,快速更新prod數據以修復從查詢窗口,其他應用程序運行的數據問題等)。很多時候應用程序被替換,約束都會丟失。

0

但還是我們的應用有用戶註冊過程中檢查 的 用戶的輸入是否是有效的(唯一的)與否, 沒有說,只與DB 約束,我們將簡單地得到一個 錯誤。

這是我讀過的最有趣的東西。你只是得到一個錯誤?這真的只是你需要的權利?曾聽說過錯誤陷阱?試試Catch響鈴嗎?

對於您的應用程序「檢查」,它實際上非常反效。數據庫將會檢查約束條件,爲什麼要這樣做呢。該應用程序應該插入行,就好像它會很好。數據庫將檢查唯一性並在失敗時提出錯誤...您的應用程序應該捕獲該錯誤,並執行您現有支票中的任何操作。

+0

這些書很不錯,因爲我使用自定義的JSF異常處理程序來重定向我每次捕獲一個Exception時都會轉到page_not_found.jsf,並且由於ConstraintViolationException是Exception的一個子類,它也會被捕獲並重定向到頁面。不太確定我的用戶會對此感到滿意。 – 2010-09-02 17:06:48

+0

依靠從數據庫拋出的錯誤通常意味着你一次只能得到一個錯誤,導致糟糕的用戶體驗。如果您預先檢查您的所有問題,可以一次顯示給用戶。 – Shlomo 2010-09-02 22:05:27

0

是的。只要抓住關鍵違規錯誤,關鍵約束就能爲您完成工作,而不必額外承擔額外的檢查費用。