2013-07-31 37 views
0

我有一個使用Record/Squeryl作爲ORM框架的liftweb應用程序。 這裏是我的架構:squeryl:如何使用oneToMany關係來構建查詢

object AppSchema extends Schema { 
    import org.squeryl.dsl.OneToManyRelation 

    val groups = table[Group]("groups") 
    val domains = table[Domain]("domains") 

    val groupToDomains = 
    oneToManyRelation(groups, domains). 
     via((g, d) => g.id === d.groupId) 
} 

object Group extends Group with MetaRecord[Group] with Loggable { 

} 

class Group extends Record[Group] with KeyedRecord[Long] with Loggable { 
    override def meta = Group 
    @Column(name = "id") override val idField = new LongField(this) 
    val name = new StringField(this, 700, "") 
    @Column(name = "date_added") val createdAt = new DateTimeField(this) 

    lazy val domains: OneToMany[Domain] = AppSchema.groupToDomains.left(this) 
} 

object Domain extends Domain with MetaRecord[Domain] with Loggable { 

} 

class Domain extends Record[Domain] with KeyedRecord[Long] { 
    override def meta = Domain 

    @Column(name = "id") override val idField = new LongField(this) 
    @Column(name = "group_id") val groupId = new LongField(this) 
    val name = new StringField(this, 700, "") 
    @Column(name = "date_added") val createdAt = new DateTimeField(this) 

    lazy val group: ManyToOne[Group] = AppSchema.groupToDomains.right(this) 
} 

我試圖實現其計算域的組中的功能:

def countDomainsInGroup(group: Group): Long = { 
    val l = from(AppSchema.domains)(d => where(d.groupId === group.id) compute(count())) 
    println("Count domains: " + l.statement) 
    l.single.measures 
} 

這將生成以下SQL:

Select 
    count(*) as c0 
From 
    domains domains1 
Where 
    (domains1.group_id = 45) 

現在一切這樣做可以,但我想應該有一個快捷方式,因爲我們已經有了group.domains,它已經定義了正確的WHERE語句 。但是,當我嘗試使用這樣的:

def countDomainsInGroup(group: Group): Long = { 
    val l = from(group.domains)(d => compute(count())) 
    println("Count domains: " + l.statement) 
    l.single.measures 
} 

我碰到下面的SQL生成:

Select 
    count(*) as c0 
From 
    (Select 
    domains8.name as domains8_name, 
    domains8.id as domains8_id, 
    domains8.group_id as domains8_group_id, 
    domains8.date_added as domains8_date_added, 
    From 
    domains domains8 
    Where 
    (45 = domains8.group_id) 
) q1 

正如你所看到的,在這裏產生一個子查詢,我不需要。我究竟做錯了什麼?

回答

0

如果仔細查看OneToMany/ManyToOne,您會發現它們擴展了Query。它們基本上便於執行查詢,通過主鍵檢索與父代或子代相關的所有對象。如果你這樣看,你看到的SQL並不奇怪。你正在詢問查詢結果的數量,而Squeryl在輸出SQL時故意使用文字,這樣你就可以自己優化,而不必擔心重寫。如果子查詢不是最優的,那麼沒有理由爲什麼你必須計算關係的計數。

+0

是的,我可以理解這一點。我不明白,是怎麼算組域無子查詢,就像這樣:選擇 COUNT(*) 從 域domains8 凡 (45 = domains8.group_id) – Uniqus

+0

但你必須爲正確的查詢以上。您的countDomainsInGroup函數是正確的,正如您所述,它會輸出您正在查找的SQL。 –

+0

但是這個查詢不是最優的。這不是我需要的。現在我實現了'Group.countDomains'輔助方法,該方法在沒有任何子查詢的情況下發出簡單的'select count(*)...'查詢。我的應用中有很多相互關聯的模型,所以我必須在任何地方實施這樣的輔助方法=/ – Uniqus