後世のために Lift メーリングリストから転載 ( source here ):
JPA の使用方法について少し説明します。どの種類のコンテナを使用しているかわかりませんが、JBoss 4.2.2 を使用し、その接続プール機能を使用しています。
scalajpa ライブラリーを使用して JPA を初期化し、エンティティー・マネージャーへの参照をスレッド・ローカル変数に保持します。RequestVar のライフサイクルは通常の HTTP リクエストよりもやや複雑であり、接続がプールにタイムリーに返されない可能性があるため、特に Lift RequestVarEM は使用しません。
最初のステップは、「モデル」を作成し、persistence.xml のユニット名をポイントすることです。
object MyDBModel extends LocalEMF("unitName", false) with
ThreadLocalEM
また、一部の操作を簡単にするために、少しコードを作成しました。各永続クラスは、いくつかの基本的な JPA 操作を提供する に混在しています。
trait Persistent {
def persist = DBModel.persist(this)
def merge = DBModel.merge(this)
def remove = DBModel.remove(this)
}
例えば、
@Entity
@Table{val name="person"}
class Person extends Persistent {
@Id
var id:String = _
@Column {val name="first_name", val nullable = false, val
updatable=false}
var firstName:String = _
@Column {val name="last_name", val nullable = false, val
updatable=false}
var lastName:String = _
@OneToMany{ ... }
var roles:Set[Role] = new HashSet[Role]()
// etc.
}
主にマップされたコレクションを使用してオブジェクト モデルをナビゲートし、より複雑なデータベース メソッドをコンパニオン オブジェクトに配置して、MyDBModel への参照がコード全体に散らばらないようにします (ご指摘のとおり、望ましくない方法です)。例えば:
object Person {
def findByLastName = MyDBModel.createQuery[Person]
("...").findAll.toList
// etc.
}
最後に、Lift との統合は、各リクエストをラップするコードの形式です。
S.addAround(new LoanWrapper {
def apply[T](f: => T):T = {
try {
f
}
catch {
case e => MyDBModel.getTransaction.setRollbackOnly
}
finally {
MyDBModel.cleanup
}
}
})
ここでは、アイデアを明確にするためにいくつかのエラー処理を省略していますが、その意図は、各 HTTP 要求がトランザクションで実行され、全体として成功または失敗することです。MyDBModel は最初に触れたときに初期化されるため、テスト コードでは、必要に応じて EM を調整でき、データ オブジェクトはこの構成から分離されます。
これが役に立つことを願っています。
ショーン