JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Object Relational Mapping » Hibernate  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
己加入精華區
by browser at 2007-03-30 02:21
本主題所含的標籤
無標籤
作者 分層設計的一些疑問 [精華]
ffmm





發文: 46
積分: 0
於 2007-03-29 01:31 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
HI 各位先進
小弟近日有些疑問想請教各位,是關於 layer design 的一些問題
目前小弟的架構是有分成
view/presentation<-->web controller<--> service <--> data access

其中 data access 是利用 hibernate 來進行
小弟的疑惑是 假設我們有一個 domain object 叫做 Category
而 Category 又可以包含 Category (目錄底下還有目錄 parent/children 關係)
於是我把 parent category 的 children mapping 設定 lazy=true
按照常見做法 這種 collection 的 mapping 用 lazy
那麼今天透過 controller 透過 service 向 dao 取得一個 category 的時候
children 是 lazy load 的狀態 這個時候呼叫了
parent.children 就會發生 lazyInitializationException
我看了很多論壇文章跟說法 就是使用 openSessionInView 這種模式
旦不解的是 如果今天開發的這個 API 是給其他客戶使用來 embed
別人不一定可以為了你掛上 那個 OpenSessionInView Filter
那麼從取出來的 Category 他的 children collection 又是 lazy 的狀態
的的確確 你的 Category object 又有 chldren 這個 property 可以存取
無法禁止使用這個 API 的人不去使用
使用又會發生 exception
那這個時候 分層設計 應該怎麼解決這個問題
小弟想了想似乎在 Hibernate In Action 一書中 作者稱為 evil 的 DTO
似乎是一個方法 也就是把 Category 這個 Domain object 再轉成
CategoryDTO (或是 CategoryVO) 然後丟出去給 controller 或是 view 使用
請問這種做法是否又回到了過去 EJB 那種 smell?
因為小弟看到的 opensource 系統
清一色都是不管這個問題 反正撈出來的 detached hibernate object 就往前丟
而開發 controller 或是 view 的人員也都不會出現我剛剛說的
誤用了物件 lazy 的 property ...
或是乾脆直接掛 OpenSessionInView 這類的東西
請問各位實務開發先進 design 這樣的東西 其 service 接口 應該如何設計?
還是要從 service 這一層出去的東西 都應該把 lazy 的東西填滿起來在丟出去?
不曉得這樣描述是否太混亂~~~~
期待高人指點一二


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:ffmm]
cw1057





發文: 11
積分: 0
於 2007-03-29 09:24 user profilesend a private message to usersend email to cw1057reply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
我個人是很不喜歡讓session染指到web層(或甚是service層)啦,session乖乖待在dao層就好!
因為這樣很容易『不小心』去改到某個欄位,也許只是顯示、計算或暫存使用,但session自動就把這個修改送給db了!

我遇到過的情況大概分三類:
首先,列表顯示的時候通常不會用『多』的資料,所以不用去initialize『多』。
1
2
3
4
5
6
  @SuppressWarnings("unchecked")
  public List<User> listUser(int first, int max) {
    DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
    criteria.addOrder(Order.asc("account"));
    return this.getHibernateTemplate().findByCriteria(criteria, first, max);
  }

第二,單筆顯示的時候會用到『多』的資料,那就另外去initialize就好。
1
2
3
4
5
6
7
  @SuppressWarnings("unchecked")
  public Inventor getInventor(Long id) {
    Inventor obj = (Inventor) this.getHibernateTemplate().get(
        Inventor.class, id);
    this.getHibernateTemplate().initialize(obj.getAttachment());
    return obj;
  }

最後,不幸的是,列表要用到『多』的資料,但又可以分層兩種情況,第一是真的要逐筆把『多』顯示出來,第二只是要顯示『aggregation』之類的資料,像是『多』的筆數,或者『多』的資料的某個欄位的最大值之類的,前者我不是逐筆去
initialize就是用select new FooVO(theParent, theChild) from ...的方式,後者就用formula。
1
2
  <!-- 發言數 -->
  <property name="postCount" formula="(select count(*) from ForumMsg_Post p where p.boardId = id)"/>


koji edited on 2007-03-29 09:46
reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:ffmm]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2007-03-29 10:09 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
很少遇到
要馬寫controller的都是自己人..
更甚於可能一個功能view~service ~dao都是同個人
所以自己知道要撈什麼..

如果效率還ok,像我們transaction也是包在service method上
所以在service要怎撈都可以.
當然出了service才發現要撈的話就只好service內再呼叫一次initialize
如果怕n+1或者事前就知道,那就dao下hql時就把該撈的fetch好

所以...你們的客戶到底是哪個層之後的使用者
這應該跟你就算不用or mapping solution, JDBC寫出來的一樣你應該要讓客戶知道這dao or Service可以撈到哪些東西, 不能說就看method名稱吧!?

另外掛opensessioninviewFilter應該要看實作?
我記得Spring的會把session設成fluch.NEVER
然後如果有transaction的部分就透過HibernateTransactionManager
就應該不用擔心會從service外面被寫入db.

koji


reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:分層設計的一些疑問 [Re:cw1057]
ffmm





發文: 46
積分: 0
於 2007-03-29 10:47 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
cw1057 wrote:
我個人是很不喜歡讓session染指到web層(或甚是service層)啦,session乖乖待在dao層就好!
因為這樣很容易『不小心』去改到某個欄位,也許只是顯示、計算或暫存使用,但session自動就把這個修改送給db了!

太酷了 我以為我寫成這樣還會遭致重貼重寫的命運
結果竟然有前輩看的懂小弟的囈語 Big Smile 好言歸正傳
當初我所持的意見就是不希望 session 的東西染指 core 以外
這樣不但把 api deliver 給客戶用的時候有一種強迫中獎(要他們用 api 順便掛上一個 filter) 也暴露了 core 的實作細節(用 hibernate)
小弟現在的任務需求 主要是希望系統的 service / dao 都可以被抽換
也就是能讓其他的 implementation 掛上來( Spring of course)
不希望 session 染指
又希望 dao implementation 可以用 hibernate 以外的 technology 實作(iBatis or JDBC or plain file system )
主要還是考慮如果把一個 detached object 丟出去
用的人 存取了 lazy 的 property 發生 exception~~ 我想她一定會丈二金剛摸不著頭緒....DTO 那種方式似乎可以解決這種誤用
只不過我們就會多搞多寫那些 DTO 的東西
也許還要寫個 Assembler 來把 domain object 轉成 DTO 再丟
大原則問題就是 用 API 的人可能跟我們 team 完全無關
所以當暴露 Service 給他用 比方
1
2
3
CategoryService cs = new CategoryService();
Category c = cs.getCategoryById(18);
 

這裡獲得的 c 就是 Category 這樣的 domain object(detached)
其中 c.getChildren() 所 mapping 的是 lazy collection
這樣一用 就發生了 lazyInitailizationException (當然現在說的是沒有 session 的狀況)
我們給客戶這樣的 API 自然無法阻止客戶用 這樣的寫法
但是客戶就會有疑問 為什麼會發生這樣的 exception
(這時候除了解釋 hibernate 或是告訴他掛上 OpenSessionInView 我不知道還有什麼方法)
如果說 Hibernate 出來是為了讓我專注於解決 Bussiness Logic
那這個時候 不是使用 這個 API 正好出了一個矛盾!?
為什麼會出現 lazy exception

當然這可能是小弟 API design 的問題 所以才特地來此寶地求教
各位大大是否可以多給一些意見指導


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:koji]
ffmm





發文: 46
積分: 0
於 2007-03-29 10:57 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
koji wrote:
很少遇到
要馬寫controller的都是自己人..
更甚於可能一個功能view~service ~dao都是同個人
所以自己知道要撈什麼..

如果效率還ok,像我們transaction也是包在service method上
所以在service要怎撈都可以.
當然出了service才發現要撈的話就只好service內再呼叫一次initialize
如果怕n+1或者事前就知道,那就dao下hql時就把該撈的fetch好

所以...你們的客戶到底是哪個層之後的使用者
這應該跟你就算不用or mapping solution, JDBC寫出來的一樣你應該要讓客戶知道這dao or Service可以撈到哪些東西, 不能說就看method名稱吧!?

另外掛opensessioninviewFilter應該要看實作?
我記得Spring的會把session設成fluch.NEVER
然後如果有transaction的部分就透過HibernateTransactionManager
就應該不用擔心會從service外面被寫入db.

koji


Thanks! 客戶會用的是 service 這一層
我們把 controller 撰寫人就當作客戶了
所以我不希望使用 service 的人知道後面在用什麼 technology 也不希望破壞他們的其他設計 自然就不希望他們掛上 OpenSessionInView Filter
另外就是 假如像 cw 前輩說的 如果你 把 detach object 丟出 service layer 卻又有 OpenSessionInView 的自動行為 re-attach session..那麼 service layer 存在又有何意義? 反正 re-attach 後 我要操作 甚至 controller 那邊的撰寫人員就可任意兜出她的 bussiness logic...如此 business service facade 不就形同虛設?
不是很了解這種情況下 讓 hibernate 流竄到各個 layer 的意義
一遍又一遍看 Hibernate In Action
發現作者根本沒騷到這個養處...書本一開始就說 layer 設計很好
後面又搞的讓那些東西竄到 service layer
我同意竄到 service 那邊
但是出了 service 之後 也沒也多做說明 也沒有像我遇到的情況
controller 是別人寫

Hibernate 或是 Spring 的論壇
也是有這些差不多的問題
其實把這個問題換過好了 如果使用你 API 丟出來的物件的 不是 web 端?
而那不就沒有 opensessioninview 這種東西可以用了嗎?


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:ffmm]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2007-03-29 12:09 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
1. 這要看你的客戶 兜出她的 bussiness logic又是怎麼樣的logic, 你session設的對, 他在怎樣兜也只是操作只能read only的資料,寫不回資料庫.這跟那麼就算是你不給他session, 給他夠多的資料,他也是可以去兜出一樣的東西. 不會因為你有沒有給他session,他就不能兜.
如果你要限制給他的資料,怕他亂撈有的沒的,那麼丟出exception很合理呀,讓他知道你的service確實不想給他某些關聯table的資料.

這麼說好了, 你說會出現lazyInitializationException 想避免,代表你認為他可以撈出所有關聯資料, 那麼開opensessioninview並不會讓對方多了什麼給他全部資料做不到的事情.因為opensessioninviewfilter本來就不該也預設不會讓client user更動資料,而只能讀取資料. 當然如果user手賤去把flushmode修改然後手動取得session,or 自己呼叫flush或transaction.commit之類就沒辦法避免....

2. 有關client怎麼知道該不該撈某些欄位的資料,這邊確實蠻難處理的.先假設用傳統jdbc, 那麼我給user的service,應該我在設計service時就規定了我只會撈出哪些欄位.用service的只能使用dto撈到dto限制的欄位. 如果真的很介意不想給user知道不能撈的欄位,大概就只能用dto再包一次.但是說實在我以前實作到後來,dto的關聯也是一直長.最後會發現幾乎跟relation差不多了. 所以我才說像我的service,通常都已經撈出該撈的資料.撈不到就代表不能撈.

3. 是呀我也看過蠻多討論,但是到最後只能折衷,沒辦法要漂亮又完全沒有每個人各自認為的所謂的bad smell吧.我自己做法是跟上面那位差不多,大概把該撈的都撈出來,有需要多撈什麼在去修改service,用initialize把他撈出.也是沒什麼特別想去用opensessioninview的做法.因為以前看到這個 http://www.hibernate.org/43.html#A10 依照我的理解覺得是呀如果依照分層設計,那麼照理上外面應該不要讓他想看啥就看啥,應該只能看到我給他的東西.

4. 不是web就得看看你的app是怎樣類型而定吧.而且概念一樣就是看怎樣實作了.

koji


koji edited on 2007-03-29 12:20
reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:分層設計的一些疑問 [Re:koji]
ffmm





發文: 46
積分: 0
於 2007-03-29 14:15 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
koji wrote:
1. 這要看你的客戶 兜出她的 bussiness logic又是怎麼樣的logic, 你session設的對, 他在怎樣兜也只是操作只能read only的資料,寫不回資料庫.這跟那麼就算是你不給他session, 給他夠多的資料,他也是可以去兜出一樣的東西. 不會因為你有沒有給他session,他就不能兜.
如果你要限制給他的資料,怕他亂撈有的沒的,那麼丟出exception很合理呀,讓他知道你的service確實不想給他某些關聯table的資料.

這麼說好了, 你說會出現lazyInitializationException 想避免,代表你認為他可以撈出所有關聯資料, 那麼開opensessioninview並不會讓對方多了什麼給他全部資料做不到的事情.因為opensessioninviewfilter本來就不該也預設不會讓client user更動資料,而只能讀取資料. 當然如果user手賤去把flushmode修改然後手動取得session,or 自己呼叫flush或transaction.commit之類就沒辦法避免....

2. 有關client怎麼知道該不該撈某些欄位的資料,這邊確實蠻難處理的.先假設用傳統jdbc, 那麼我給user的service,應該我在設計service時就規定了我只會撈出哪些欄位.用service的只能使用dto撈到dto限制的欄位. 如果真的很介意不想給user知道不能撈的欄位,大概就只能用dto再包一次.但是說實在我以前實作到後來,dto的關聯也是一直長.最後會發現幾乎跟relation差不多了. 所以我才說像我的service,通常都已經撈出該撈的資料.撈不到就代表不能撈.

3. 是呀我也看過蠻多討論,但是到最後只能折衷,沒辦法要漂亮又完全沒有每個人各自認為的所謂的bad smell吧.我自己做法是跟上面那位差不多,大概把該撈的都撈出來,有需要多撈什麼在去修改service,用initialize把他撈出.也是沒什麼特別想去用opensessioninview的做法.因為以前看到這個 http://www.hibernate.org/43.html#A10 依照我的理解覺得是呀如果依照分層設計,那麼照理上外面應該不要讓他想看啥就看啥,應該只能看到我給他的東西.

4. 不是web就得看看你的app是怎樣類型而定吧.而且概念一樣就是看怎樣實作了.

koji


真是太感謝 koji 無私的分享經驗
那麼像是 Category 這樣的東西她有 children & parents
在 Service 的設計上 會把 getChildren 這件事情做成 一個 method
也就是說當 Service 透過 DAO 取回 category 的時候 children 給他 lazy
想要 這個 category 的 children 的時候 再透過 Service 的 getChildren 去 call DAO 的 getChildren 來取得? 還是Service 提供的 getChildren 這個 method 實上利用 DAO 背後動手腳 eager load 那些 children 回來再 pass 給 service
(不知道這樣說 koji 是否會被我搞混 Big Smile)
因為這樣設計起來就有 service 跟 dao method 幾乎到了一對一的情況
service 有一個 getChildren... DAO 就會有一個 getChildren
(當然 service 這邊的 getChildren 可能會比 DAO 的 getChildren 來的複雜
比方說加上權限的過濾 摘掉一些不適合被看到的 category)

令人不禁懷疑 切開 service 跟 dao 的方法是否....也點 over killed
(不過我們有一個需求就是假設某天 dao implementation 是要被換的)

使用 initialize 的方法ok不過 想請問的是假如你 initailize 的那個 object
lazy 的 collection 有好幾個 每個都可以能一大串
只是為了其中一兩個 不就有點消耗?

那麼是否針對每一個 lazy 的 collection (好比 getParents / getChildren )
再 DAO 以及 Service 的設計上
都要有一個對應的介面出來?
這個可能是設計的偏好問題..不過想多了解看看各位前輩在實務工程上
精妙的做法

看了幾個例如 .Net 的 CMS -- Cuyahoga
或是幾個 sourceforge 上面比較成熟的專案
好像都沒有我現在遇到的這種怪需求
(service / dao impl 可能都會換 而且沒使用 service api 的人 還不是自己開發 service api 的人)


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:ffmm]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2007-03-29 17:29 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
嗯~這邊可能我跟你設計不同
我的session的開始結束是service的開始結束
所以我是習慣在service內呼叫catagoryDAO.getCategory
然後在category.getChildren這種方式

1
2
3
4
5
6
public Category getOwnCategory(){
 
    Category c = catagoryDAO.getCategory();
    Hibernate.iniitalize(c.getChildren());//這時是還可以用的
    return c;
}

類似這樣,當然如果是回傳list以後才這樣做會很多query,那我就會在dao裡面用fetch join.所以是看狀況.但是我這是因為我知道client需要什麼而寫的.所以如果在不套opensession的做法下,你應該先考慮一下假設不是使用hibernate,你現在是透過jdbc存取,你回傳dto時也一定是有個限界.一定不可能你把整個關聯資料都撈到dto給外面.然後再想想看可以撈到什麼程度給前端吧.我自己是這樣做的...
不知道其他人又是如何囉.

koji


reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:分層設計的一些疑問 [Re:koji]
ffmm





發文: 46
積分: 0
於 2007-03-29 19:30 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
koji wrote:
嗯~這邊可能我跟你設計不同
我的session的開始結束是service的開始結束
所以我是習慣在service內呼叫catagoryDAO.getCategory
然後在category.getChildren這種方式

1
2
3
4
5
6
public Category getOwnCategory(){
 
    Category c = catagoryDAO.getCategory();
    Hibernate.iniitalize(c.getChildren());//這時是還可以用的
    return c;
}

類似這樣,當然如果是回傳list以後才這樣做會很多query,那我就會在dao裡面用fetch join.所以是看狀況.但是我這是因為我知道client需要什麼而寫的.所以如果在不套opensession的做法下,你應該先考慮一下假設不是使用hibernate,你現在是透過jdbc存取,你回傳dto時也一定是有個限界.一定不可能你把整個關聯資料都撈到dto給外面.然後再想想看可以撈到什麼程度給前端吧.我自己是這樣做的...
不知道其他人又是如何囉.

koji


先感謝 koji 熱情回應!
如果 session 的 open/close 是在 service 的部分
那麼今天如果 dao impl 改用了 jdbc ?? 情況不就~~~
小弟的想法則是 session 的 open/close 應該會被卡在 dao 這邊
我在使用 spring+hibernate 的時候 利用 HibernateTemplate 的方法
看了文件後也在實際使用發現 例如呼叫
1
HibernateTemplate.Save(category);

則這個時候 Save 的開頭會 open session 然後 Save 的結尾會 close session

如此一來 在前提為 service impl 以及 dao impl 可以任意抽換情況下
open session 動作若放在 service 的話
不就在抽換 dao impl 的時候 會有問題?
已我初淺的理解下 我想到的方法 是每層隔離
service 不知道 dao 用什麼樣的實作
view 那邊也不知道 service 用的是什麼實作

在近日使用 hibernate 的情況下
反到覺得 hibernate 很容易讓我不小心因為用了他 反而把其特性 向上傳遞(污染?!)

只是我在抽光 hibernate 的想法後去 design 這些 layer 以及其接口
就如我上篇所說的 感覺 service / dao 所提供的 method 都會近乎一比一
而且若用這樣的 design 的話...似乎 hibernate 的優勢
就好像有點失去....(雖然的確 hibernate impl, code 可以少很多)

不知 koji 的想法又是如何..也許是我這個 design requirment 太怪異誇張
竟然想到要把 service/dao impl 都可以任意抽換....

不知是否還有其他前輩 愈過類似的問題?


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:ffmm]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2007-03-29 22:54 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
照你實作方式
你的transaction也是套在DAO上或沒套囉???

你可以用hql fetch join就可以啦!!service還是只知道呼叫method而沒有動到hibernate的code.還是說你很排斥DAO使用fetch join?

而且套session的動作靠設定spring HibernateTransactionManager處理掉了
如果真要抽離就從spring那邊下手.當然不太可能不用改任何code.

koji


reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:分層設計的一些疑問 [Re:ffmm]
ingramchen

Web monkey



發文: 479
積分: 12
於 2007-03-29 23:01 user profilesend a private message to usersend email to ingramchenreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
(1) session 就是 session ,一個長時段的操作。把 session 開關的控制權交給 dao,會造成在極短時間內開關多次 session,即耗費資源,而且完全無法從 first-level cache 得到任何好處。所以為達最佳的效能,session 能拖多長就該多長。

按 session 長度有五種設定法 (以 web app 來講):
(a) Conversation (一個 session 橫跨多個 web request)
(b) OpenSessionInView (每個 web request 一個 session )
(c) Transaction on Service Layer (每個 transaction 一個 session)
(d) Transacion on DAO layer (每個 web request 產生多個 session)
(e) no transacion (每次資料庫操作便產生一個 session)

一般來講,搭配 Spring 都是用 (b) 或是 (c),這樣寫比較有效率,能夠盡量重用已經在 session 裡的 entity。而且可以避免 NonUniqueObjectException (同個 db record 有兩個 java instance)的問題。
而 (e) 就是你說的 "則這個時候 Save 的開頭會 open session 然後 Save 的結尾會 close session"
。這是最沒效率的設計,拿 hibernate 當 jdbc 用,如果這樣寫,那乾脆不要用 hibernate 了。

(2) 一般都是一個人從頭 (view layer) 包到腳 (dao layer)。如果要把 view layer 拆給別人寫,那用 open session in view 問題會少一點。為什麼?因為 view 端的人不用為了顯示幾個屬性就頻頻來找 service layer 端的人。從 service 端人的觀點來看,你不見得能先知道 view 端的人要什麼,可以先寫好 eager fetch 給他吧?

(3) 預留未來抽換 dao implementation ? 嗯... 請問你是在寫 framework 嗎?如果不是,個人覺得沒必要留這個莫須有的彈性。即使和 hibernate 極為相似 JPA/EJB3 也沒辦法讓你設計出通用的 dao layer 來 (JPA 沒有 .saveOrUpdate(),也沒有 Flush.MANUAL,這兩個會影響 service layer 的設計)。如果硬要擠出共通的界面,就是取所有功能共通的部份,最後全部都設計成跟 jdbc + DTO 一樣... 所有的好處都沒了...

一般遇到的問題都是抽換 database... 不知有誰真的在 production system 遇過要換 dao implementation 的?願聞其詳。

(4)
"如此一來 在前提為 service impl 以及 dao impl 可以任意抽換情況下
open session 動作若放在 service 的話
不就在抽換 dao impl 的時候 會有問題? "

session 交給 service端處理屬於上述的 (c) 類,抽換 dao impl 時只要換掉套在 service 上的 PlatformTransactionManager 即可,Spring 會處理剩下的事。不過... 雖然如此,你的 service 還是有很多細部要修....

(5)
"在近日使用 hibernate 的情況下
反到覺得 hibernate 很容易讓我不小心因為用了他 反而把其特性 向上傳遞(污染?!) "

是的,hibernate session 會 "隱含地" 橫跨 layer。但是 java code 上卻完全看不到,這一直是 hibernate 所訴求的功能 - POJO based persistence,讓你在各個 layer 只要處理 pojo 即可,讓程式簡單,讓 unit test 好寫。如果要避免藏在裡面的 session... 那就不要用 hibernate 囉,hibernate 並不是設計給這種需求的.... 建議改用 jdbcTemplate or iBatis 可能會比較適合。

個人覺得如果view layer 分出去給別人做,關鍵處反而不是設計上問題... 而是溝通。不管用 hibernate open session in view (他居然不肯掛 filter ? ) 或是 jdbc + DTO (你不知要 fetch 啥給他),事前事後沒討論清楚都行不通地。


reply to postreply to post
MyBlog | 訂便當管理系統

作者 Re:分層設計的一些疑問 [Re:koji]
ffmm





發文: 46
積分: 0
於 2007-03-30 09:52 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
koji wrote:
照你實作方式
你的transaction也是套在DAO上或沒套囉???

你可以用hql fetch join就可以啦!!service還是只知道呼叫method而沒有動到hibernate的code.還是說你很排斥DAO使用fetch join?

而且套session的動作靠設定spring HibernateTransactionManager處理掉了
如果真要抽離就從spring那邊下手.當然不太可能不用改任何code.

koji


先謝過 koji Big Smile
我是把 Trasaction 套在 Service 上
不排斥使用 fetch


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:ingramchen]
ffmm





發文: 46
積分: 0
於 2007-03-30 10:20 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
就我目前看到的 spring + hibetnate 的 code 裡面
其中 hibernatetemplate 的做法就是再執行一個動作的時候就把 session open 然後 close
(我記得良葛格的 spring 一書 也有提此, 記錯不要打我 逃~~~)
另外實作中發現 spring config 把 service 套上 transaction 後, 就會發現 spring 會為我們在 transaction 開始的時候也起 session,誠如 ingramchen 大人所言..真是佩服佩服

我不知道算不算是在做 framework 哩~ 不過的確如您所述 不會在 production system 來做 impl 抽換的動作, 我們會有這樣的想法主要是因為 dao 可能會用 db 也可能會用 filesystem
所以可能要做這兩種 或是兩種以上 然後視情況 掛上所需的 impl
而掛上的動作當然是透過 sping ioc 的方法
所以會希望設計這些東西出來在每一層都能夠香對清楚的隔離
當 然不可能100% 隔離 那就太偉大了
所以特來徵詢各位的意見 了解看看工業級標準的考量是什麼
目前確實獲益良多

hibernate 訴求 pojo based 的東西我很理解 也很欣賞這種設計
不過真的是 pojo based 嗎..如果只是站在你的 java object 不用 iimplement 任何 interface or 繼承 from hibernate 的 class 而言..是沒錯 不用作這些
但是你透過 hibernate 撈出來的東西 本質就有所改變 (應該是說 老出來的東西 已經被 hibernate proxy 過了 所以這時候你呼叫 lazy load 的 property 才會發生 lazyInitializationException 而不是 nullexception)
這樣還算是 POJO 嗎?
小弟無異挑起宗教信仰 只是想起這個問題覺得 hibernate 被過度神化了一點...Gavin king 說 DTO 是 evil, 但他們自己 hibernate team 的人也持與我這幾天問的問題差不多的概念 就是 DTO 不一定 evil.
到 javaeye.org 論壇去看了很久 這種問題也是散佈各處
聯 hibernate/Nhibernate 的 forum 也有這類的問題 三不五時浮現
所以....到不是用不用 hibernate 的問題
hibernate 在使用的時候 如果一套到底 我覺得也不用 service / dao 兩層
service / dao 並起來都可以 也不會混雜到不行

嗯...非常謝謝樓上幾位前輩的熱情分享與回應
如果有更多寶願意給小弟挖 請繼續搖筆 Tongue


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:ffmm]
ingramchen

Web monkey



發文: 479
積分: 12
於 2007-03-30 11:05 user profilesend a private message to usersend email to ingramchenreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
ffmm wrote:
..43...

我不知道算不算是在做 framework 哩~ 不過的確如您所述 不會在 production system 來做 impl 抽換的動作, 我們會有這樣的想法主要是因為 dao 可能會用 db 也可能會用 filesystem
所以可能要做這兩種 或是兩種以上 然後視情況 掛上所需的 impl
而掛上的動作當然是透過 sping ioc 的方法
所以會希望設計這些東西出來在每一層都能夠香對清楚的隔離
當 然不可能100% 隔離 那就太偉大了
所以特來徵詢各位的意見 了解看看工業級標準的考量是什麼
目前確實獲益良多


file system based 的 persistence store?喔.... 你的 app 不需要 transaction 嗎?不需 atomic commit ?

ffmm wrote:
hibernate 訴求 pojo based 的東西我很理解 也很欣賞這種設計
不過真的是 pojo based 嗎..如果只是站在你的 java object 不用 iimplement 任何 interface or 繼承 from hibernate 的 class 而言..是沒錯 不用作這些
但是你透過 hibernate 撈出來的東西 本質就有所改變 (應該是說 老出來的東西 已經被 hibernate proxy 過了 所以這時候你呼叫 lazy load 的 property 才會發生 lazyInitializationException 而不是 nullexception)
這樣還算是 POJO 嗎?


POJO 這個詞是針對 EJB2 而來的,當初 EJB2 要求你實做 ejb 專用的 interface,讓 unit test 大為困難。後來才有人提出說想寫純 business code,不想外加一些有的沒的。所以 POJO 一般是指 code 這個層次,而不是 byte code 的層次。byte code 很幹淨的那種... 呃,好像沒有專門的詞。

我們一定要 POJO 嗎?其實只要邏輯明確,很好寫測試,就是個好架構。個人以為,POJO 是讓 unit test 好寫的一種 "手段"。testability 才是真的目的。

至於 lazyInitializationException 會出現,其實是因為 http 整個是 stateless 的,然後我們硬套上 以 stateful 為設計理念的 hibernate session,才會出現格格不入的怪現象。

如果你是寫 desktop app 配 hibernate,就不會出現 lazy exception 了(因為你的 session 從頭到尾都不用關....)

那麼該怎麼解決 http stateless 問題呢?有人的做法將 http 層再做一層 abstraction,讓 http 運作起來像 stateful。這種做法就是上述說的 (a) conversation。目前有實做 conversation 的只有 JBoss SEAM。SEAM 也是 hibernate 的人開發的。他們自己知道 hibernate 只適合在 stateful 的環境下操作,所以主導 SEAM 的開發,推廣 stateful 的開發架構。

ffmm wrote:
小弟無異挑起宗教信仰 只是想起這個問題覺得 hibernate 被過度神化了一點...Gavin king 說 DTO 是 evil, 但他們自己 hibernate team 的人也持與我這幾天問的問題差不多的概念 就是 DTO 不一定 evil.
到 javaeye.org 論壇去看了很久 這種問題也是散佈各處
聯 hibernate/Nhibernate 的 forum 也有這類的問題 三不五時浮現
所以....到不是用不用 hibernate 的問題
hibernate 在使用的時候 如果一套到底 我覺得也不用 service / dao 兩層
service / dao 並起來都可以 也不會混雜到不行

嗯...非常謝謝樓上幾位前輩的熱情分享與回應
如果有更多寶願意給小弟挖 請繼續搖筆 :P


沒人神話 hibernate 啊?不是說不適合就不要用了嗎.... 一般來講 hibernate 只適合用在
(1) domain logic 複雜的環境
(2) 你的團隊願意解決、有能力解決 web stateless 和 hibernate session 間的麻煩事

如果不適合,那麼使用前就要再三考慮了。有時候也不是單單技術上的問題,團隊對於 hibernate 的熟練程度也需要納入考量。

至於 DTO,用了 hibernate 也不是完全不需要用 DTO,當你要做 remote 時,就非用 DTO 不可。沒有一定說什麼什麼是 evil 的。

招式是死的,人是活的


reply to postreply to post
MyBlog | 訂便當管理系統

作者 Re:分層設計的一些疑問 [Re:ffmm]
dnho





發文: 11
積分: 0
於 2007-04-01 16:16 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
小弟想請問一下這樣的分層設計會有什麼好處呀?
我是新手,請多多指教Blush


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:dnho]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2007-04-03 20:59 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
dnho wrote:
小弟想請問一下這樣的分層設計會有什麼好處呀?
我是新手,請多多指教Blush

可以減少method內的程式行數
這樣要看跟修改時都方便

還有增加程式重複利用性
譬如我dao的method寫出來
可能很多service都會用到這個method去取東西
就不用每個service method都放一模一樣的code

還有可以套transaction方便~等等的好處

koji


reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:分層設計的一些疑問 [Re:ffmm]
dnho





發文: 11
積分: 0
於 2007-04-22 04:39 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
那再請問一下,在DAO層的程式碼是埶行SQL,那在service層做的是先整理好SQL語句再把SQL傳過去DAO那埶行?

reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:dnho]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2007-04-22 09:01 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
dnho wrote:
那再請問一下,在DAO層的程式碼是埶行SQL,那在service層做的是先整理好SQL語句再把SQL傳過去DAO那埶行?

no..通常都dao裡面就寫好了
service只把參數條件丟給dao...

如果整理好再丟過去,不就連參數都得在service整理好,
那dao的method不就只執行list而已?

所以都會把sql這些放到dao設計吧,我記得appfuse也是這種模式
可以抓appfuse來看看囉

koji


koji edited on 2007-04-22 10:00
reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:分層設計的一些疑問 [Re:dnho]
ingramchen

Web monkey



發文: 479
積分: 12
於 2007-04-22 09:54 user profilesend a private message to usersend email to ingramchenreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
dnho wrote:
那再請問一下,在DAO層的程式碼是埶行SQL,那在service層做的是先整理好SQL語句再把SQL傳過去DAO那埶行?

no, DAO 封裝所有 persistent 的邏輯,所有跟 persistent 有關的東西都要寫在 DAO 裡。
Service 層只是調度這些物件一起合作而已,所以不宜寫 SQL。


reply to postreply to post
MyBlog | 訂便當管理系統

作者 Re:分層設計的一些疑問 [Re:ffmm]
pipp





發文: 104
積分: 1
於 2008-01-07 10:16 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
不好意思,我想這問題剛好跟我的問題類似

剛好我也是把架構切的跟發文的ffmm 大一樣
在期間遇到一些問題,因為我再service是直接回傳hibernate的entity回去給action,
因為EntityA可能會包含了很多的子集合(set),會遇到問題例如要算最低價,
但必須是由 EntityA 的 包含的set a1, a1又是包含set B1 才能夠算出來,
1
2
3
4
5
Entity A
     set<A1> a1
                   
Entity A1
     set<B1> b1


像這樣的情況下,我算最低價的邏輯到底該在 Service 還是 寫在 Entity 裡面?
這是常常有爭執的地方,我把邏輯寫在Service裡面,
由Service去呼叫Dao或是其他Service取得資料來計算,結果回傳EntityA
也有人說寫在EntityA裡面,但是如此一來就必須Fetch足夠的Data給EntityA
且還要一路傳到web端

這問題還蠻常在會議裡吵,所以來這邊問問各位的意見


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:pipp]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2008-01-07 10:19 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
統計相關的邏輯要不要乾脆從sql下手?
不然你這種撈法跟取法..會算個好幾圈吧?

koji


reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:分層設計的一些疑問 [Re:koji]
pipp





發文: 104
積分: 1
於 2008-01-07 10:34 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
謝謝板大
目前我的做法就是呼叫Dao並
已經有從sql 端下手拉,還給他建立一個view
但主要還是有人會有疑問邏輯到底該在哪裡?


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:pipp]
pipp





發文: 104
積分: 1
於 2008-01-07 11:04 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
因為同事他們去上分析設計的課程,
老師都會說 這個物件一定會有一個方法叫做取得最低價,
所以它們就覺得這個責任的歸屬該在這個Entity身上,
其實我也知道...但是不想把一大堆沒用的資料都回傳到前端,
也可能我寫過EJB所以已經習慣都把邏輯封在Session bean
所以請問大家的意見


reply to postreply to post
作者 Re:分層設計的一些疑問 [Re:pipp]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2008-01-07 11:06 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
都從sql下手的話還有分邏輯在哪嗎?
不太懂你所謂的邏輯又是什麼邏輯?

放到entity or sessionbean又跟前端又有何關係呢?
entity的話不就是model層了還是跟前端沒關係呀

koji


reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:分層設計的一些疑問 [Re:koji]
pipp





發文: 104
積分: 1
於 2008-01-07 11:16 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
不好意思 說得不清不楚
除了sql 之外還有一些其他的運算如:判斷庫存等..

跟前端的確沒有關係,因為我是直接回傳這個Entity
前端的呼叫的確一點差別都沒有

但是我如果把算低價以及判斷庫存等寫在Entity的取的最低價這個method
勢必也得把足夠的資料也fetch在entity裡面才有辦法算
然後還要把這個entity pass 到前端

如果我再Service端做,只要把算出來的結果,存在entity
不必傳一大堆資料

浪費板大的時間拉,拍謝


reply to postreply to post
go to first page go to previous page  1   2  go to next page go to last page
» JWorld@TW »  Object Relational Mapping » Hibernate

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8