[转帖]Scala中使用Hibernate事务的处理_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3261 | 回复: 0   主题: [转帖]Scala中使用Hibernate事务的处理        下一篇 
shuangqiang.xing
注册用户
等级:上尉
经验:737
发帖:64
精华:0
注册:2013-10-30
状态:离线
发送短消息息给shuangqiang.xing 加好友    发送短消息息给shuangqiang.xing 发消息
发表于: IP:您无权察看 2013-11-1 9:01:26 | [全部帖] [楼主帖] 楼主

     目前在做的一个用Scala写的项目Oschat中,之前用了Scala Slick ORM框架来操作数据库,感觉有点不太好用,想想还是换回Hibernate吧。这样别人用起来会方便一点。之前Slick我也没去看它的事务是怎么处理的,既然现在换回了Hibernate,当然得考虑一下。项目中没打算去集成Spring之类的框架,那么事务的处理就得自己处理了。

       Websocket的通信是服务器与客户端保持一个长连接,每次发消息过来不是一个单独请求,当然也不会产生一个单独线程。那么我就考虑通过AOP方式对方法进行拦截,用Scala的话可以通过混入式编程的方式来实现AOP。但是拦截的方法是trait中固定的,这里就很不方便了。所以我这里采用了将方法作为参数传递给基类的方法,在基类来做session的创建销毁,transaction的开启提交。

具体实现


     1.定义一个处理Hibernate SessionFactory的基类,这里创建Session用了openSession方法,并没有用getCurrentSession方法。因为我们是对service的每个方法进行拦截,如果前一个方法提交了事务,那么getCurrentSession产生的Session就会被自动Close掉了。接着调用获取的Session就无法打开了

abstract class SessionFactoryHelper {

       lazy val sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory()
       var _session:Session = _
       def getSession = if(_session!=null && _session.isOpen()) _session else sessionFactory.openSession()

}

     2、定义一个BaseService,这里定义个接受方法作为参数的方法,然后在该方法的前后处理事务。在warpSession方法中,我们调用了f,也就是子类中穿过来的方法。然后在它的前后处理了事务。

abstract class BaseService extends SessionFactoryHelper{

       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
       }
}

     3、具体的业务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)
       }
}

     4、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
       }

}

     5、测试代码与结果

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




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论