【问题标题】:Mapper versus Record/SquerylMapper 与 Record/Squeryl
【发布时间】:2013-02-05 19:16:22
【问题描述】:

我即将在 Lift 框架中开始我的第一个项目,我必须决定选择哪个持久性库。我即将使用关系后端,因此 Mapper 和 Record 都可以发挥作用。

在 Mapper 的情况下——我最想念的是控制发送到 RDBMS 的查询的能力——尤其是当涉及到更复杂的查询时,这些查询将通过 SQL 中的连接、聚合等来解决。举个例子——让我们有以下两个实体:

class BaseProduct extends LongKeyedMapper[BaseProduct] with IdPK {
  // some fields
}
object BaseProduct extends BaseProduct with LongKeyedMetaMapper[BaseProduct]

class MyProduct extends LongKeyedMapper[MyProduct] with IdPK {
  // some fields
  object base extends MappedLongForeignKey(this, BaseProduct)
}
object MyProduct extends MyProduct with LongKeyedMetaMapper[MyProduct]

其中MyProductBaseProduct 实体的特化之一。这些实体之间显然存在一对一的关系。然而,我想出的查询确切的MyProduct 及其BaseProduct 的最佳可能性是这样的查询:

MyProduct.findAll(PreCache(MyProduct.base))

哪个发出两个查询(而且我恐怕无法控制我想选择MyProduct实体的哪些字段。

对 Mapper 库来说已经够糟糕了。我对 Record/Squeryl API 的主要担忧是它缺少 Mapper API 周围存在的所有 Proto-classes。是否有接近这些类的记录功能的东西?是否可以访问 Squeryl 中的数据库特定功能(例如 PostgreSQL 中的几何查询)?

这两个层还有其他优缺点吗?或者,如果我想对与数据库的通信进行适当的类型安全封装,并且可以对查询进行适当的控制,是否还有其他值得关注的抽象层(我习惯于直接使用 PHP 中的 PDO 层发出查询 - 我不想要这样一个直接的查询界面,但是有一些可以控制查询的可能性会很大)与 Lift 框架集成绝对是一个优势。

谢谢!

【问题讨论】:

    标签: scala lift squeryl


    【解决方案1】:

    我们已经将 Squeryl 与 Lift 结合使用已有一段时间了,并且对它非常满意。根据您的上述情况,在当前版本的 Squeryl (0.9.5) 中,您可以执行以下操作:

    class BaseProduct(id:Long, some more fields) extends KeyedEntity[Long] {
    
    }
    
    class MyProduct(id:Long, some more fields) extends KeyedEntity[Long] {
    
    }
    

    然后,您将拥有一个定义 relationships 之类的架构(我假设它们在 ID 字段中加入):

    val baseProducts = Table[BaseProduct]("base_products")
    val myProducts = Table[MyProduct]("my_products")
    val myProductsToBaseProducts = 
      oneToManyRelation(myProducts, baseProducts).via((mp, bp) =>
        mp.id === bp.id)
    

    要查询两条记录,您可以执行以下操作:

    from(myProducts, baseProducts) ( (mp, bp) =>
      where(mp.id === bp.id and mp.id === LOOKUPVAL) 
      select(bp, mp) )
    

    上面的查询将从单个 SQL 选择返回一个 (BaseProduct, MarketProduct) 元组。

    您也可以使用关系来检索相关项目,例如通过将此方法添加到MyProduct

    def baseProduct = myProductsToBaseProducts.left(this)
    

    但是,就像您在 Mapper 中的示例一样,它将发出第二个查询。至于进行特定于数据库的查询,& 运算符将允许您在服务器上评估表达式。如果该功能在 Squeryl 中不可用,您可以创建 custom functions

    总的来说,我发现 Squeryl 非常灵活,是 ORM 和直接 SQL 之间的完美混合体。它的性能非常好,而且我还没有找到太多 Squeryl 禁止我轻松获取所需数据库功能的地方。下一个版本会变得更加容易,因为 0.9.6 将具有更多的灵活性 custom types

    【讨论】:

    • 谢谢! Squeryl 似乎很适合我......还有一个问题 - 我想没有开箱即用的支持(由 Mapper 框架中的 Proto-classes 提供)不适用于 Record/Squeryl。或者你知道一些具有类似功能的库吗? (或者如果我想要这个功能而不自己工作,我必须将 Squeryl 和 Mapper 集成到一个项目中?)
    • 目前没有使用 Squeryl/Record 的开箱即用实现。我的理解是,没有的唯一原因是因为ProtoUser 中的id 和Squeryl 的KeyedEntity 定义主键中的id 之间存在冲突。对于 0.9.6,这应该很容易解决,并且可能会在它发布时得到修复。同时,我可能会做的只是复制 ProtoUser 的代码并修改您自己的版本以解决冲突。
    猜你喜欢
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 2015-10-03
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多