2013-02-05 48 views
3

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

在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类。一些与Record的这些类的功能接近的东西?是否可以访问Squeryl中的数据库特定功能(例如几何PostgreSQL中的查询)?

这些图层中是否有其他优点和缺点?还是有任何其他的抽象层,如果我想与数据库有良好的类型安全封装的通信封装,并提供对查询的体面控制(我曾被用来直接使用PHP中的PDO层发布查询 - 不想要这样的直接查询接口,但有一些控制查询的可能性会很大)与Lift框架的集成绝对是一个优势。

谢谢!

回答

5

我们一直在使用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)) 

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

您还可以使用的关系来获取相关项目,如通过添加这种方法MyProduct

def baseProduct = myProductsToBaseProducts.left(this) 

然而,就像从映射你的榜样,它会发出第二个查询。至于进行数据库特定查询,有&运算符,它允许您在服务器上评估表达式。如果该功能在Squeryl中不可用,您可以创建custom functions。总之,我发现Squeryl非常灵活,并且是ORM和直接SQL之间的一个很好的混合体。它的表现非常好,我没有发现太多Squeryl禁止我轻松获取所需数据库功能的地方。在下一个版本中它变得更加容易,因为0.9.6在custom types上具有更大的灵活性。

+0

谢谢! Squeryl对我来说似乎是一个很好的选择......还有一个问题 - 我认为没有开箱即用的支持(如Mapper框架中的Proto类所提供的)不适用于Record/Squeryl。或者你知道一些具有类似功能的库吗? (或者我必须将Squeryl和Mapper集成到一个项目中,如果我需要这个功能而不需要自己动手的话) –

+0

Squeryl/Record目前没有现成的实现。我的理解是,没有唯一的原因是由于ProtoUser中的id和定义主键的Squeryl的KeyedEntity中的id有冲突。使用0.9.6时,这应该很容易解决,并且在发布时可能会被修复。同时,我可能会做的只是复制ProtoUser的代码并修改您自己的版本以解决冲突。 – jcern