Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Orm 如何将会话/事务获取封装到Squeryl中关系的lazy init中?_Orm_Scala_Squeryl - Fatal编程技术网

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

Orm 如何将会话/事务获取封装到Squeryl中关系的lazy init中?,orm,scala,squeryl,Orm,Scala,Squeryl,我正在尝试使用Squeryl实现一对多关系,并遵循以下步骤 本文档给出了以下示例: object SchoolDb extends Schema { val courses = table[Course] val subjects = table[Subject] val subjectToCourses = oneToManyRelation(subjects, courses). via((s,c) => s.id === c.s

我正在尝试使用Squeryl实现一对多关系,并遵循以下步骤

本文档给出了以下示例:

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.subject
subject.courses
的任何调用都需要包装在事务中。然而,我使用ORM的目标之一是对调用方隐藏这些细节。因此,我不希望调用代码必须在事务中包装对这些字段的调用

如果我修改示例,将lazy 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)
线程“main”java.lang.RuntimeException中的异常:没有会话绑定到当前线程,必须通过session.create创建会话
并通过“work”或“bindToCurrentThread”绑定到线程
在scala.Predef$.error处(Predef.scala:58)
在org.squeryl.Session$$anonfun$currentSession$1.apply上(Session.scala:111)
在org.squeryl.Session$$anonfun$currentSession$1.apply上(Session.scala:111)
位于scala.Option.getOrElse(Option.scala:104)
在org.squeryl.Session$.currentSession(Session.scala:110)上
在org.squeryl.dsl.AbstractQuery.org$squeryl$dsl$AbstractQuery$$\u dbAdapter(AbstractQuery.scala:116)
位于org.squeryl.dsl.AbstractQuery$$anon$1。(AbstractQuery.scala:120)
位于org.squeryl.dsl.AbstractQuery.iterator(AbstractQuery.scala:118)
位于org.squeryl.dsl.DelegateQuery.iterator(DelegateQuery.scala:9)
但是,正如我所说,如果我将调用方包装在一个事务中,那么一切都会正常工作


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

我假设您在调用courses对象时遇到了这个错误

我不太了解Squiryl是如何工作的,但我相信OneToMany[课程]是一个活生生的对象。这意味着对courses对象的调用需要一个会话,因为任何调用都可能延迟地转到数据库获取数据


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

Hmm,也许我的示例太简单了。实际上,我并不是在尝试来自squeryl文档的示例,但我的代码并不复杂(结构上的唯一区别是我的代码有更多的列)。我通过调用伴生对象中的函数来获取对象的实例,该函数确实使用事务,但从封装的角度来看,这似乎很好,因为伴生对象链接到DB支持的类。我的应用程序实际上没有任何用户交互(除了用户启动它)。它只是生成报告。由于您正在创建报告,我假设您没有进行任何写入。将整个操作打包到事务中不应有任何损害。