在Grails中,如何在视图和控制器中使用中间连接类处理多对多?

时间:2013-04-16 01:45:04

标签: grails

假设我有以下域名:

class Store {
    String name

    static hasMany = [ products: StoreProduct ]
}

class Product {
    String name

    static hasMany = [ stores: StoreProduct ]
}

class StoreProduct {
    BigDecimal discount

    static belongsTo = [ store: Store, product: Product ]
    static mapping = {
        id composite: ['store', 'product']
    }

换句话说,StoreProduct之间存在多对多关系,中间StoreProduct域类跟踪每个商店的个别折扣。

Grails内置支持一对多关系,因此您可以使用正确的字段名称传递ID列表,控制器会自动将ID解析为实体列表。但是,在这种情况下,它是一个多对多的中间域类。

我在Store编辑视图中尝试了以下代码,以允许用户选择产品列表:

<g:each in="${products}" var="product" status="i">
    <label class="checkbox">
        <input type="checkbox" name="products" value="${product.id}"/>
         ${product.name}
    </label>
</g:each>

但Grails会根据我对name属性使用的内容抛出各种错误。我还尝试了以下input名称:

products
products.product
products.product.id
product[0].product
product[0].product.id

但它们都没有正常工作。

我的问题是,Grails中是否存在对此类关系的内置支持,特别是在视图方面?

2 个答案:

答案 0 :(得分:1)

按如下方式更改您的域名结构:

class Store {
    String name

    Set<Product> getProducts() {
       StoreProduct.findAllByStore(this)*.product
    }
}

class Product {
    String name
    Set<Store> getStores() {
        StoreProduct.findAllByProduct(this)*.store
    }
}

import org.apache.commons.lang.builder.HashCodeBuilder
class StoreProduct implements Serializable {

    BigDecimal discount
    Store store
    Product product

    static mapping = {
        id composite: ['store', 'product']
        version false
    }

boolean equals(other) {
    if (!(other instanceof StoreProduct)) {
        return false
    }

    other.store?.id == store?.id &&
        other.product?.id == product?.id
}

int hashCode() {
    def builder = new HashCodeBuilder()
    if (store) builder.append(store.id)
    if (product) builder.append(product.id)
    builder.toHashCode()
}
}

答案 1 :(得分:0)

来自上面的域类: -

  • 其中一个域(StoreProduct)必须通过belongsTo来承担关系的责任。有关详细信息,请参阅API

  • 包含StoreProduct主键的域类(composite)应实现Serializable

如果可用,请提供一个堆栈跟踪进行调试。