目前在作的一個用Scala寫的項目Oschat中,以前用了Scala Slick ORM框架來操做數據庫,感受有點不太好用,想一想仍是換回Hibernate吧。這樣別人用起來會方便一點。以前Slick我也沒去看它的事務是怎麼處理的,既然如今換回了Hibernate,固然得考慮一下。項目中沒打算去集成Spring之類的框架,那麼事務的處理就得本身處理了。 java
Websocket的通訊是服務器與客戶端保持一個長鏈接,每次發消息過來不是一個單獨請求,固然也不會產生一個單獨線程。那麼我就考慮經過AOP方式對方法進行攔截,用Scala的話能夠經過混入式編程的方式來實現AOP。可是攔截的方法是trait中固定的,這裏就很不方便了。因此我這裏採用了將方法做爲參數傳遞給基類的方法,在基類來作session的建立銷燬,transaction的開啓提交。 git
1.定義一個處理Hibernate SessionFactory的基類,這裏建立Session用了openSession方法,並無用getCurrentSession方法。由於咱們是對service的每一個方法進行攔截,並不和當前線程綁定。因此若是前一個方法提交了事務,那麼getCurrentSession產生的Session就會被自動Close掉了。接着調用獲取的Session就沒法打開了 sql
object SessionFactoryHelper { lazy val sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory() var _session:Session = _ def getSession = if(_session!=null && _session.isOpen()) _session else sessionFactory.openSession() }二、定義一個BaseService,這裏定義個接受方法做爲參數的方法,而後在該方法的先後處理事務。在warpSession方法中,咱們調用了f,也就是子類中穿過來的方法。而後在它的先後處理了事務。
abstract class BaseService { def getSession = SessionFactoryHelper.getSession def withTransaction[T](f: => T): T = warpSession(f) private def warpSession[T](f: => T): T = { if(getSession.getTransaction().wasCommitted()) getSession.getTransaction().begin() println("Transaction begin") val t = f if(getSession.getTransaction().isActive()) getSession.getTransaction().commit() getSession.close() println("Transaction commit") t } }三、具體的業務Service,這裏會將當前session穿給每個dao,在每一個dao執行完之後,咱們會提交事務。這裏咱們每個方法實際上是調用了BaseService的 withTransaction方法,而後把裏面的方法體傳給基類。
class MemberService extends BaseService{ private val dao = new MemberDao(getSession) def getMemberbyUsername(username:String):Member= withTransaction{ dao.getMemberbyUsername(username) } def getMemberbyUid(uid:String):Member =withTransaction{ dao.getMemberbyUid(uid) } }
四、Dao的代碼,這裏咱們應該加一個BaseDao,來處理一些公用的方法 數據庫
class MemberDao (session:Session){ def getMemberbyUsername(username:String):Member={ val sql = "from me.feng.domain.Member t where t.username=?" val q = session.createQuery(sql).setParameter(0, username) getFirst(q).asInstanceOf[Member] } def getMemberbyUid(uid:String):Member = { println(session.toString) session.get(classOf[Member],uid).asInstanceOf[Member] } def getFirst(q:Query):Any ={ if(q.list().size()>0) q.list().get(0) else null } }五、測試代碼與結果
object DaoTest { def main(args: Array[String]) { val d = new MemberService() val m =d.getMemberbyUsername("254662") val m2 =d.getMemberbyUid("254662") println(m.nickname) println(m2.createTime) } }
Transaction begin Dao getMemberbyUsername Transaction commit Transaction begin Dao getMemberbyUid Transaction commit ForEleven 2013-08-26 16:57:22.0
這樣的方法還算是比較簡單的了,只是在寫Service方法的時候 = 後多了一個withTransaction 編程