代码之家  ›  专栏  ›  技术社区  ›  egervari

Lift JPA应用程序的良好架构是什么?

  •  3
  • egervari  · 技术社区  · 16 年前

    我想知道在电梯中使用JPA模型的最佳实践是什么?我 注意,在JPA演示应用程序中,只有一个模型对象 这就像一个超级物体,可以做任何事情。我不这么认为 可能是最可扩展的方法,不是吗?

    在提升中仍然做刀型是明智的吗?例如, 有些代码看起来有点膨胀,可以简化 在所有模型对象中:

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

    可以是:

    AuthorDao.remove(someId)
    

    我很感激你给我一些建议 电梯的工作方式也很容易组织和维护。最好是有人在中型到大型升降机上实际使用JPA,而不是仅仅假设Spring做什么(我们知道如何做);)

    第一阶段的发展将是大约30-40张桌子,并且 最终会超过100…我们需要一种可扩展、整洁的方法。

    1 回复  |  直到 16 年前
        1
  •  2
  •   Will Sargent    16 年前

    从电梯邮件列表中转发给后代( source here ):

    我可以稍微了解一下我们如何使用JPA。我不知道是哪种 您正在使用的容器,但我们使用的是JBoss 4.2.2,以及 使用其连接池设施。

    我们使用scalajpa库来初始化jpa内容并保留 在线程局部变量中引用实体管理器。我们 特别是不要使用提升请求变量,因为 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,数据对象与此隔离 配置。

    希望这是有用的。

    肖恩