從後人(source here)的電梯郵件列表轉貼:
我可以揭示我們如何使用JPA一盞小燈。我不確定你正在使用什麼樣的容器,但我們正在使用JBoss 4.2.2和 使用它的連接池功能。
我們利用scalajpa庫來初始化JPA的東西,並在線程局部變量中保留對實體管理器的引用。我們 明確地不使用Lift RequestVarEM,因爲RequestVar的生命週期比普通的HTTP請求 稍微複雜一些,並且這可能導致連接不及時地返回到池中的 。
的第一步是創建「樣板」,並在單位名稱 從你的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.
}
最後,我們與電梯一體化是一些代碼的形式 包裹每個請求:
S.addAround(new LoanWrapper {
def apply[T](f: => T):T = {
try {
f
}
catch {
case e => MyDBModel.getTransaction.setRollbackOnly
}
finally {
MyDBModel.cleanup
}
}
})
我省略了一些錯誤處理這裏,使想法更清楚,但是 的意圖是每個HTTP請求都在一個事務中執行,而這個事務要麼全部成功,要麼全部失敗。由於MyDBModel是 ,當它初次觸摸時,在您的測試代碼中,您可以根據需要配置 EM,並且數據對象與此 配置隔離。
希望這是有用的。
肖恩
你如何測試嚴重依賴全局變量的代碼(如你的例子中的'MyDBModel')。如果不涉及整個堆棧,是不是很複雜? – Theo 2010-06-14 05:24:29