简体   繁体   English

Grails数据绑定一对多关系

[英]Grails data binding one-to-many relationship

I am trying to take advantage of Grails' ability to handle data binding for a one-to-many association. 我正在尝试利用Grails的能力来处理一对多关联的数据绑定。 I am able to successfully assigning to the relationship but removing single elements or all of them is not working. 我能够成功分配关系,但是删除单个元素或所有元素均无法正常工作。

Here is an example of what my model looks like: 这是我的模型的示例:

class Location {
    Float latitude
    Float longitude
}

class Route {
    Location start
    Location stop

    static belongsTo: [courier: Courier]
}

class Courier {
    String name
    static hasMany = [pickups: Location]
}

class ScheduledCourier extends Courier {
    static hasMany = [routes: Route]

    static mapping = {
        routes(cascade: 'all-delete-orphan')
    }
}

When creating a new ScheduledCourier object via a website, I can pass a list of Routes to automatically bind with markup like this: 当通过网站创建一个新的ScheduledCourier对象时,我可以传递一个路由列表来自动绑定标记,如下所示:

<input type="hidden" name="routes[0].latitude" value="5" />
<input type="hidden" name="routes[0].longitude" value="5" />
<input type="hidden" name="routes[1].latitude" value="10" />
<input type="hidden" name="routes[1].longitude" value="10" />

This works for me just fine in my controller: 这对我来说在我的控制器中正常工作:

class CourierController {
    // Very simplistic save
    def saveScheduled = {
        def courier = new ScheduledCourier(params)
        courier.save()
    }

    // Very simplistic update
    def update = {
        def courier = Courier.get(params.id)
        courier.properties = params
        courier.save()
    }
}

If I use the following markup instead, I can step through the debugger and see that the routes property is now [] and the object saves fine but the records are not removed from the database. 如果我改用以下标记,则可以逐步调试程序,然后可以看到routes属性现在为[],该对象可以很好地保存,但记录不会从数据库中删除。

<input type="hidden" name="routes" value="" />

In addition, if I sent markup like this: 另外,如果我发送这样的标记:

<input type="hidden" name="routes[0].latitude" value="5" />
<input type="hidden" name="routes[0].longitude" value="5" />

courier.routes will not be updated to only contain the 1 object. courier.routes将不会更新为仅包含1个对象。

Has anyone seen this behavior? 有人看到过这种行为吗?

This is Grails 1.3.7...at least for now. 至少目前是Grails 1.3.7...。

Wrote an integration test that reproduces this behavior: 编写了一个重现此行为的集成测试:

public void testCourierSave() {
    def l1 = new Location(latitude: 5, longitude: 5).save(flush: true)
    def l2 = new Location(latitude: 10, longitude: 10).save(flush: true)

    def params = ["name": "Courier", "pickups[0].id": l1.id, "pickups[1].id": l2.id,
        "routes[0].start.id": l1.id, "routes[0].stop.id": l2.id,
        "routes[1].start.id": l2.id, "routes[1].stop.id": l1.id]

    def c1 = new ScheduledCourier(params).save(flush: true)

    assertEquals(2, c1.routes.size())

    params = [routes: ""]
    c1.properties = params
    c1.save(flush: true)
    c1.refresh()    // Since the Routes aren't deleted, this reloads them

    assertEquals(0, c1.routes.size())    // Fails

    assertEquals([], Route.findAllByCourier(c1))    // Fails if previous assert is removed
}

I wonder if the following is happening: 我想知道是否正在发生以下情况:

When passing the params [routes:""] the framework is ignoring it as it's just an empty string. 当传递params [routes:""] ,框架将忽略它,因为它只是一个空字符串。

Similarly <input type="hidden" name="routes[0].latitude" value="5" /> probably just updates the zeroth route entry in the collection, the others aren't deleted because all you've told it is that the latitude value of the zeroth route should be 5, not that this is should now be the only route in the collection. 同样, <input type="hidden" name="routes[0].latitude" value="5" />可能只是更新集合中的第零个路由条目,其他的不会被删除,因为您所知道的是第零条路线的纬度值应为5,而不是现在应该是集合中的唯一路线。

To get the effect you want, you'll need to add a routes.clear() before binding the parameters. 为了获得想要的效果,您需要在绑定参数之前添加routes.clear()

To control when the state of the model is persisted to the database you can use Spring transactionality which is available in Grails. 要控制何时将模型状态持久化到数据库中,可以使用Grails中可用的Spring事务性 This would allow you to revert to the original state of the object if subsequent processing failed. 如果后续处理失败,这将允许您还原到对象的原始状态。 eg: 例如:

Courier.withTransaction {status ->

  // Load the courier

  //clear the existing routes

  // bind the new properties

  // perform extra processing

  //if the object is invalid, roll back the changes
  status.setRollbackOnly()

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM