Java分層中遇到的問題
陸陸續續寫了一些Java的專案,用了Spring系列和Hibernate這樣的框架。在設計Service層和Dao層的時候碰到了一些想不清楚的問題。
以一個簡單的使用者資訊管理功能為例,如果不用Spring Data之類的東西。那麼我一般會這麼寫程式碼
controller往上沒什麼好說的,controller呼叫service就好了,service呼叫dao。
關鍵在於service這裡。我可能會這麼寫
...
@Autowired
UserDao userDao;
public void saveUser(String userName){
userDao.save(userName);
}
public User findUser(String userName){
return userDao.findUser(userName);
}
...
然後在整個service的實現類上面註解@Transaction
Dao實現的程式碼就是
...
@Autowired
SessionFactory sessionFactory;
public void save(String userName){
Session session=sessionFactory.getCurrentSession();
session.save(userName);
}
...
問題就來了,如果按照這樣的寫法,那麼首先Hibernate的一級快取似乎就沒有起到作用了。
因為在Dao中,每一個方法都獲取一個Session來進行操作,方法間並不共享Session。也就是說如果Service的一個方法中呼叫了Dao的兩個方法,這兩個方法的Session不一樣,一級快取根本沒用。
其次就是Service層中查詢出來的物件是遊離態的。
在Service的方法中如果find了一個物件然後呼叫這個的物件的Set方法,資料庫中是不會更新的。因為呼叫Dao的find方法後Session關閉,物件從持久態變成了遊離態,所以這時候要更新物件的資訊只能手動再寫一句update(User u)
,就是這樣:
public void update(String userName,String password){
User u=userDao.findUser(userName);
u.setPassword(password);
userDao.update(u);
}
這顯然是不好的一種方式。
但是如果想改掉前面兩個缺點,就必須把Session提到Service層,讓Service的一個方法用一個Session,這樣上面提到的兩個問題就都能解決。可是Session本應該是Dao層的東西,提升到Service層似乎也是不好的做法。
不知道這裡頭的矛盾到底怎麼解決?