如何将会话/事务获取封装到Squeryl中关系的lazy-init中?

时间:2011-01-28 06:24:55

标签: orm scala squeryl

我正在尝试使用Squeryl实现一对多关系,并遵循instructions on their site

文档提供了以下示例:

object SchoolDb extends Schema {    
  val courses = table[Course]    
  val subjects = table[Subject]      
  val subjectToCourses =
    oneToManyRelation(subjects, courses).
    via((s,c) => s.id === c.subjectId)  
}

class Course(val subjectId: Long) extends SchoolDb2Object {    
  lazy val subject: ManyToOne[Subject] = SchoolDb.subjectToCourses.right(this)
}

class Subject(val name: String) extends SchoolDb2Object {    
  lazy val courses: OneToMany[Course] = SchoolDb.subjectToCourses.left(this)
}

我发现对Course.subjectSubject.courses的任何调用都需要包含在事务中。但是,我使用ORM的目标之一是隐藏呼叫者的这些细节。因此,我不希望调用代码必须在事务中包含对这些字段的调用。

似乎我修改了示例以在事务中包装惰性init函数,如下所示:

class Subject(val name: String) extends SchoolDb2Object {    
  lazy val courses: OneToMany[Course] = {
    inTransaction {
      SchoolDb.subjectToCourses.left(this)
    }
}

我得到以下异常:

Exception in thread "main" java.lang.RuntimeException: no session is bound to current thread, a session must be created via Session.create 
and bound to the thread via 'work' or 'bindToCurrentThread'
    at scala.Predef$.error(Predef.scala:58)
    at org.squeryl.Session$$anonfun$currentSession$1.apply(Session.scala:111)
    at org.squeryl.Session$$anonfun$currentSession$1.apply(Session.scala:111)
    at scala.Option.getOrElse(Option.scala:104)
    at org.squeryl.Session$.currentSession(Session.scala:110)
    at org.squeryl.dsl.AbstractQuery.org$squeryl$dsl$AbstractQuery$$_dbAdapter(AbstractQuery.scala:116)
    at org.squeryl.dsl.AbstractQuery$$anon$1.<init>(AbstractQuery.scala:120)
    at org.squeryl.dsl.AbstractQuery.iterator(AbstractQuery.scala:118)
    at org.squeryl.dsl.DelegateQuery.iterator(DelegateQuery.scala:9)

但是,就像我说的,如果我在一个事务中包装调用者,那么一切正常。

那么,我如何封装这个对象由对象本身的数据库支持的事实呢?

1 个答案:

答案 0 :(得分:1)

我假设你在课程对象的调用中遇到这个错误?

我不太了解Squeryl是如何工作的,但我相信OneToMany [Course]是一个实时对象。这意味着对课程对象的调用需要一个会话,因为任何调用可能会懒洋洋地进入数据库以获取数据。

如何组织这取决于您使用的应用程序类型。在Web应用程序中,添加过滤器(第一个入口点)以启动和停止事务通常是有意义的。在GUI客户端,比如一个swing应用程序,它是一个很好的解决方案,可以在您收到用户交互时启动事务。这样你就可以获得不长的交易,也可以延伸你希望以原子方式执行的调用(完全或根本不执行)。