卧龍會:軟體Hibernate session開啟與資料庫物理連接的時間關係
文|原創:卧龍會 Arivn
先說結論:
spring openSession獲取到的是hibernate session,並沒有實際獲取綁定資料庫連接。
不到最後一刻,不操作db就不會獲取實際的資料庫連接。當第一次操作db時,hibernate session 才會綁定資料庫物理連接。這樣降低了session使用資料庫連接時間片段,最大化的利用鏈接資源。
所以spring連接打開的session是hibernate Session,原創微信公眾號:卧龍會IT技術。並不是實際資料庫連接,可放心使用(提前Open hibernate Session 對資料庫鏈接無消耗,所以spring filter才能幫助用戶提前打卡session)
註:以下是基於hibernate和spring集成的前提下進行的。
一般spring的事物是配置在service上,所以來說service和controller上的情況
1
service 層情況
綁定資料庫物理連接是在第一次操作資料庫的時候發生。操作資料庫包括查詢,修改,刪除,新增,當然還有事物。在service中後續的db操作繼續使用第一次綁定的資料庫連接,直到service方法退出結束。
對於非事物的查詢(PROPAGATION_SUPPORTS)
不管你在service查詢前做了什麼複雜的業務,都不會綁定資料庫鏈接
如下代碼:
對於事物。開啟事物時打開鏈接(PROPAGATION_REQUIRED)
進入方法就綁定了資料庫鏈接,所以事物裡面的邏輯單元應該精簡,不要有太多和事物無關的邏輯。比如提交一個http請求,在請求中會浪費掉資料庫鏈接的時間
service方法中調用內部其他方法
只會綁定一次資料庫連接,第二次操作DB使用的是第一次操作DB綁定的鏈接,同樣會把事物特性傳遞下來。
注意:上面的代碼 baseDAO.save(bean)和 this.saveOptLog(id)並不會觸發真實的保存和提交。事物和自動提交是加在service層,getById不會觸發事物的開啟和自動提交。如果saveOptLog是其他servcie中注入的方法會自動開啟的事物,但是繼續使用同一連接,如下代碼:
2
controller 情況
每調用一次service都會綁定一個資料庫物理連接,並且執行完後釋放掉。
原因:service是spring注入進來的代理service,有事物增強處理。
如果是處理重複業務數據,preparestatement不一定會生效。
原因:controller重複調用service的方法綁定到的資料庫連接不一定是同一個,preparestatement是基於同一連接生效的。如果preparestatement要生效需要放在service內處理。
3 控制代碼劃分規則建議
一般來說service根據模塊功能和解耦,裡面可能會包含部分的業務邏輯控制代碼;controller本身是控制層,也會包含部分邏輯控制代碼。那麼邏輯控制代碼怎麼區分是方在service層還是controller呢?
如果是處理比較複雜的業務請求,並且可能消耗的時間比較久(正常情況應該走MQ進行非同步處理,但這個地方討論不能走非同步必須面對的情況)。需要把消耗時間的業務邏輯控制上浮,放在controller中處理,即使是同一service。
erivce和controller的規則:
1 根據模塊功能劃分,並進行解耦
當仁不讓,第一規則,優先考慮。
2 serivce層的邏輯粒度盡量小,盡量單一
保持service方法的邏輯簡潔性,往往一個方法處理邏輯過多會很容易造成代碼混亂,並且不容易維護。
3 在小粒度的方法前提下,控制業務邏輯進行上浮
如果是非事物,可以考慮吧邏輯代碼上浮到controller,由controller進行組合調用service介面。
如果是事物業務,必須把代碼邏輯放在service層,但也需要保持每個方法的小粒度,再由一個方法來進行業務邏輯層控制,並暴露給contrller使用。
當然非業務的事物情況下,也可以把部分contrller裡面共同的邏輯,下潛到service實現。(具體根據service具體業務屬性進行劃分)
但同上,每個子方法都應該具有小粒度和單一的特性。
為什麼要這樣做?
在上面提到,當第一次操作db後,如果方法一直沒執行完並退出,會一直佔用鏈接。這段時間鏈接是無法被其他人使用的,哪怕鏈接處於空閑狀態。
這樣的結果就是100個複雜的業務來了,service層使用了100個數據鏈進行長時間處理(連接池只提供100個鏈接),這時其他一個執行查詢的小業務請求來了,由於鏈接全部被佔用了,這時這地101個請求就無法處理,只有等。
如果service足夠簡單,讓controller來控制部分業務邏輯(由一個一個小粒度的service方法組成),
A 調用一個service方法結束後會先把鏈接釋放出來;
B 這時其他業務請求才有可能獲取到鏈接,並進行處理,小請求處理完後會釋放鏈接;(能很快的做出相應)
C 之前的contrller繼續調用serivce方法,綁定到釋放的鏈接,繼續處理。(響應速度延遲不大)
這樣100個鏈接能支持100個以上的請求業務,才能【實現高並發】。否則100個鏈接提供的並發支持非常有限。
關鍵思路:
1 調用小粒度service方法,讓使用完後,及時釋放,盡量避免不用但一直佔用資源的時間段產生
2 讓使用db資源的時間片儘可能的小,處理過程中可以讓其他需要資源的業務請求也能夠參與進來 。原創微信公眾號:卧龍會IT技術。
3 讓想用資源的能及時用到資源,佔用資源但空閑狀態的釋放資源,【最大化】利用有限的資源。
以上是大多數情況下的處理方式,但不能一篇而論。需要根據功能模塊和業務場景選擇性的使用。
---好東西就要分享給你朋友圈---
TAG:卧龍會IT技術 |