3

我想知道 Lift 中 JPA 模型的最佳实践是什么?我注意到在 jpa 演示应用程序中,只有一个 Model 对象,它就像一个可以完成所有工作的超级对象。我不认为这可能是最具可扩展性的方法,不是吗?

在 Lift 中仍然做 DAO 模式是否明智?例如,有些代码看起来有点臃肿,可以在所有模型对象中进行简化:

Model.remove(Model.getReference(classOf[Author], someId))

可能:

AuthorDao.remove(someId)

我将不胜感激任何有关设置与 Lift 想要的工作方式相匹配并且易于组织和维护的东西的提示。最好来自在中型到大型 Lift 站点上实际使用过 JPA 的人,而不是仅仅假设 Spring 做了什么(我们知道怎么做);)

开发的第一阶段将是大约 30-40 个表,最终将超过 100 个……我们需要一种可扩展的、简洁的方法。

4

1 回答 1

2

为后代从电梯邮件列表重新发布(来源在这里):

我可以稍微说明一下我们如何使用 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.

}

最后,我们与 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,并且数据对象与此配置隔离。

希望这是有用的。

肖恩

于 2010-06-14T05:19:09.900 回答