2012-05-10 49 views
3

在以下示例中,我希望Product.searchAll與 添加劑和產品都匹配,但它似乎忽略了eq('name', taste)Grails GORM'或'不與協會合作

class Additive { 
    String flavor 
    static belongsTo = [product:Product] 
} 

class Product { 
    String name 
    static hasMany = [additives:Additive] 

    static constraints = { 
      name nullable:true 
    } 

    static namedQueries = { 
     searchAll { taste -> 
      or { 
       eq('name', taste) 
       additives { eq('flavor', taste) } 
      } 
     } 
     searchAdditives { taste -> 
      additives { eq('flavor', taste) } 
     } 
     searchProducts { taste -> 
      eq('name', taste) 
     } 
    } 
} 

class SearchSpec extends grails.plugin.spock.IntegrationSpec { 
    def choc, muff 

    def 'searchAll should return products and additives that match - THIS FAILS'() { 
     setup: 
      createTestProducts() 
     expect: 
      Product.searchAll("chocolate").list() == [choc, muff] 
    } 


    def 'searchProducts should return only products that match - THIS PASSES'() { 
     setup: 
      createTestProducts() 
     expect: 
      Product.searchProducts("chocolate").list() == [choc] 
    } 

    def 'searchAdditives should return only additives that match - THIS PASSES'() { 
     setup: 
      createTestProducts() 
     expect: 
      Product.searchAdditives("chocolate").list() == [muff] 
    } 

    private def createTestProducts() { 
     // create chocolate 
     choc = new Product(name:'chocolate').save(failOnError:true, flush:true) 
     // create a chocoloate-flavored muffin 
     muff = new Product(name:'muffin').addToAdditives(flavor:'chocolate').save(failOnError:true, flush:true) 
    } 
} 

生成的SQL如下:

select this_.id as id1_1_, this_.version as version1_1_, 
this_.name as name1_1_, additives_1_.id as id0_0_, 
additives_1_.version as version0_0_, additives_1_.flavor as 
flavor0_0_, additives_1_.product_id as product4_0_0_ from product 
this_ inner join additive additives_1_ on 
this_.id=additives_1_.product_id where (this_.name=? or 
(additives_1_.flavor=?)) 

是不是有什麼毛病我的語法,或者這是使用Grails,GORM或H2的問題嗎?

回答

5

我的猜測,快速查看您的查詢,是Grails/GORM正在執行inner join。只有在表格之間存在關係時,內部聯接纔會匹配。在上面的例子中,該查詢將從決不會匹配choc,因爲choc沒有任何關聯的添加劑。

因此,這不是or這是失敗的,這是實際的查詢。啓動localhost:8080/{yourapp}/dbConsole並運行相同的查詢,但沒有where語句。你應該看到你只能得到含有一種或多種添加劑的產品。

我相信(未測試),你可以強制使用LEFT JOIN語法是這樣的:

這應該強制左(或外部)連接,允許沒有匹配的添加劑產品。注意:使用外部連接時可能會得到重複結果,但這取決於您的特定使用場景。

+0

感謝您的提示 - 將調查! – Alex

+0

開箱即用 - 感謝您的幫助!你認爲這是Grails 2中的一個錯誤嗎?很確定這在1.3.7和HSQLDB一起工作。 – Alex

+0

如果我記得,這是Grails或Hibernate中已知的變化。這是出於性能原因。我不是100%同意,因爲它會影響你可以有0個相關項目的任何關係。 : - \ – OverZealous