从后人(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