2

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)

しかし、私が言ったように、呼び出し元をトランザクションでラップすると、すべてが機能します。

では、このオブジェクトがデータベースによってバックアップされているという事実をオブジェクト自体にカプセル化するにはどうすればよいでしょうか?

4

1 に答える 1

1

コースオブジェクトの呼び出しでこのエラーが発生すると思いますか?

Squerylがどのように機能するかについてはよくわかりませんが、OneToMany[Course]はライブオブジェクトであると思います。つまり、coursesオブジェクトの呼び出しにはセッションが必要です。これは、呼び出しがデータベースに遅れてデータをフェッチする可能性があるためです。

これをどのように編成するかは、使用するアプリケーションのタイプによって異なります。Webアプリケーションでは、トランザクションを開始および停止するためのフィルター(最初のエントリポイント)を追加することが理にかなっていることがよくあります。スイングアプリケーションなどのGUIクライアントでは、ユーザーの操作を受け取った時点でトランザクションを開始することをお勧めします。そうすることで、長くはなく、アトミックに実行されると予想される呼び出しにまたがるトランザクションを取得できます(完全に実行されるか、まったく実行されないかのいずれか)。

于 2011-01-28T07:14:53.197 に答える