2015-10-26 32 views
0

在Grails框架中,我看到了命令對象模式,但其用法對我來說不是很清楚。另外Grails文檔給出的大多數例子都是關於域類而不是命令對象的(可能簡化代碼示例)。命令對象只在控制器中,還是可以傳遞給服務層?

1 - 命令對象是在視圖和控制器層之間使用的東西,必須留在那裏?

2 - 或者將命令對象傳遞給服務層是一種很好的做法嗎?

爲了說明點2:

class MyController { 

    def updateUserPassword (UserPasswordCommand cmd) { 
     ... 
     myService.updatePassword(cmd) 
     ... 
    } 
} 

如果點2是一個不好的做法,那你怎麼提交的數據傳遞給服務層?通過域類? 編輯:似乎確定

[編輯]

如果我使用命令對象,而不是域類在這種情況下該怎麼做:

def signup(UserCreateCommand cmd) 
{ 
    if (!cmd.hasErrors()) { 
      def userInstance = userService.signup(cmd) 
     } 
    } 
    if (cmd.hasErrors()) { 
     /* Stay on form in order to display errors */ 
     render(view:"/app/authentication/_signupForm", model:[userCreateCommand: cmd]) 
     return 
    } 
    ... 
} 

什麼發生,如果在用戶業務辦理結束時,有數據庫突然出現異常(因爲刷新數據不尊重模式約束)?

在我的觀點的問題是,有兩個疑問:

首先 - 呼叫cmd.hasErrors()時,有一個持續的要求對電子郵件唯一約束例如

其次 - 當服務事務結束時,有一個對數據庫的刷新(在我的情況下會導致一個SQL插入),並且可能引發具有唯一約束的列電子郵件上的例外

Test cmd.hasErrors()不會阻止大小寫數據庫引發違反約束唯一例外,或者我錯了?

+2

將命令對象發送到服務是一種非常好的做法。 –

+0

@JoshuaMoore感謝您的建議,我編輯了我的問題,並用命令對象指定了一個特定的案例,您的建議將會很有趣 – Nico

+1

我認爲命令對象的目的是做數據綁定並將http請求包裝進一個對象而不是隱含的參數。在我看來,服務層不應該知道命令對象,而應該知道業務實體,它們可能是您的域或DTOS,它們被dao層用來實際更新實體。想象一下,服務層被其他客戶端暴露並在企業中重用,這些客戶端可能不是一個窗體,因此沒有可用的Command,但他們可能通過傳遞User或UserDto來調用該服務。有什麼想法嗎? – Viriato

回答

2

這是將請求參數傳遞給服務層的最佳方式。我看到有人通過params服務,這實際上是最糟糕的做法。我們的控制器應該是轉儲,控制器方法中的最大5-8 LOC是我公司的指導原則。

Command對象給你這麼大的權力出像驗證,方法等

+0

謝謝Uday,我編輯了我的問題與一個特定的情況下,如果你有一個建議,它將受到歡迎 – Nico

0

約束喜歡獨特這就需要從數據庫中驗證的,不能命令對象上應用的盒子。在這種情況下,您可以使用驗證器http://grails.github.io/grails-doc/2.5.1/ref/Constraints/validator.html

您還可以使用importFrom約束將所有約束形成User域到命令對象http://grails.github.io/grails-doc/2.5.1/guide/validation.html

+0

我已經這樣做,但如果我驗證我的命令對象與cmd.hasErrors()返回true( cmd.email =「[email protected]」),但是當我決定調用userService.saveMyUser(cmd)時,其他用戶只在數據庫中保存電子郵件[email protected]。當我的事務完成時,對數據庫的刷新可能會拋出異常,因爲我嘗試插入[email protected],但它已經在數據庫中。我希望我的例子很清楚。 – Nico

+0

,因爲數據庫中會有兩個查詢,第一個用於唯一:真正的電子郵件,第二個用於數據庫刷新用戶。 – Nico

+0

對不起,我的意思是cmd.hasErrors()返回false,並且userService發現錯誤 – Nico

相關問題