Squeryl を使用して 1 対多の関係を実装しようとしており、サイトの指示に従っています。
ドキュメントには、次の例が示されています。
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 を使用する際の私の目標の 1 つは、これらの詳細を発信者から隠すことです。そのため、呼び出しコードでこれらのフィールドへの呼び出しをトランザクションでラップする必要はありません。
次のように、トランザクションで遅延初期化関数をラップするように例を変更すると、次のようになります。
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)
しかし、私が言ったように、呼び出し元をトランザクションでラップすると、すべてが機能します。
では、このオブジェクトがデータベースによってバックアップされているという事実をオブジェクト自体にカプセル化するにはどうすればよいでしょうか?