2016-03-26 22 views
0

IがGORM(私は無関係なフィールドを省略)を使用して、データベースに格納されているようなエンティティた:GORM - 1(少なくとも2)に変更3つのクエリを

class Payment { 
    static hasMany = [paymentEntries: PaymentEntry] 
} 

class PaymentEntry { 
    static hasOne = [category: PaymentCategory] 
    static belongsTo = [payment: Payment] 
    static constraints = { 
    category(nullable: true) 
    } 
} 

class PaymentCategory { 
    static hasMany = [payments: PaymentEntry, rules: PaymentRule] 
    String name 
} 

だから、我々は上に支払いを持って、どの缶多くのPaymentEntryを持ち、各PaymentEntryは1つのPaymentCategoryに属することができます。

いくつかの条件を満たすPaymentsを選択する必要がありますが、PaymentEntriesも特定のカテゴリに属する​​ものだけを選択してください。現在、私は3つのクエリでそれを行う:

private static List<PaymentCategory> getCategories(String category) { 
    def result = null 
    if (category != null && category.length() > 0) { 
     def c = PaymentCategory.createCriteria() 

     result = c { 
      ilike("name", "%${category}%") 
     } 
    } 

    result 
} 
:カテゴリ名の一部にフィットし、またはちょうど(私たちは関係なく、自分のエントリのカテゴリのすべての支払いをしたいような場合には)カテゴリのクエリを省略

  1. カテゴリを選択PaymentCategoryに基づい

  2. 選択PaymentEntriesのid、:

    private static List<Long> paymentEntryIds(String category) { 
        def categories = getCategories(category) 
        def c = PaymentEntry.createCriteria() 
    
        def result = new ArrayList() 
    
        // If category is selected, but there is no matching category, return empty list 
        if (!categorySelectedButNoMatch(category, categories)) { 
         result = c { 
          if (category == null) { 
           isNull("category") 
          } else if (categories != null && categories.size() > 0) { 
           inList("category", categories) 
          } 
    
          projections { 
           property("id") 
          } 
         } 
        } 
    
        result 
    } 
    
  3. 最後に選択支払い、特定Paymenが含まれているものに限定されましたtEntries:

    def paymentEntriesIds = paymentEntryIds(selectedCategory) 
    
    def c = Payment.createCriteria() 
    
    def result = new ArrayList() 
    
    // If there are no payment entries matching category criteria, we return empty list anyway, so there 
    // is no need querying payments. 
    if (paymentEntriesIds.size() > 0) { 
        result = c { 
         paymentEntries { 
          inList("id", paymentEntriesIds) 
         } 
    
         if (importEntryId != null) { 
          eq("importEntry.id", importEntryId) 
         } 
         if (query != null) { 
          ilike("description", query) 
         } 
         // Omitted ordering and paging 
        } 
    } 
    
    result 
    

これは動作しますが、それはデータベースへの3つのクエリを実行します。私はこのコードがより洗練されていると確信しており、それは少ないクエリで行うことができます。それを改善する方法に関するすべてのアイデアは大歓迎です。

+0

ジョインを使うことを考えます。あなたの支払い基準のcreateAlias 'paymentEntries'、 'paymentEntries'、JoinType.LEFT_OUTER_JOINなど – user3718614

答えて

0

少なくとも3つの異なるメソッドを使用できます。デタッチされたクエリ、HQLのクエリとサブクエリのサブクエリです。基準とDetachedQueryの

例は次のようになります。

def subquery = new DetachedCriteria(PaymentCategory).build {   
    projections { 
     groupProperty 'id' 
    } 

    ilike("name", "%${category}%") 
} 

次にあなたが別のクエリでは、このサブクエリを使用することができます。私は正確にあなたのドメイン上でそれをテストしていない

return PaymentEntry.createCriteria().list {   
    category { 
     inList "id", subquery 
    } 
} 

、これはちょうどべきアイデアを示す。 GORMドキュメントのDetachedCriteria部分を参照してください:https://grails.github.io/grails-doc/latest/guide/single.html#detachedCriteria

非常に複雑なクエリで使用します。アソシエーションを正常に動作させるには、時にはcreateAliasが必要になることがあります。

+0

あなたの質問に対する最初のコメントに述べられているように - これはサブクエリよりも優れています。 – droggo

関連する問題