Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Data binding Grails-从数据绑定上的hasMany关联列表中删除项?_Data Binding_Grails_Groovy_Dns_Associations - Fatal编程技术网

Data binding Grails-从数据绑定上的hasMany关联列表中删除项?

Data binding Grails-从数据绑定上的hasMany关联列表中删除项?,data-binding,grails,groovy,dns,associations,Data Binding,Grails,Groovy,Dns,Associations,Grails提供了自动创建域对象并将其绑定到hasMany列表的能力,如中所述 因此,例如,如果我的域对象“Author”有许多“Book”对象的列表,我可以使用以下标记(来自《用户指南》)创建和绑定这些对象: 在这种情况下,如果指定的任何书籍都不存在,Grails将创建它们并适当地设置它们的标题。如果指定索引中已有书籍,则将更新它们的标题并保存它们。我的问题是:有没有简单的方法告诉Grails从数据绑定的“books”关联中删除其中一本书 最明显的方法是省略与要删除的域实例对应的表单元素;

Grails提供了自动创建域对象并将其绑定到hasMany列表的能力,如中所述

因此,例如,如果我的域对象“Author”有许多“Book”对象的列表,我可以使用以下标记(来自《用户指南》)创建和绑定这些对象:


在这种情况下,如果指定的任何书籍都不存在,Grails将创建它们并适当地设置它们的标题。如果指定索引中已有书籍,则将更新它们的标题并保存它们。我的问题是:有没有简单的方法告诉Grails从数据绑定的“books”关联中删除其中一本书

最明显的方法是省略与要删除的域实例对应的表单元素;不幸的是,根据用户指南,这不起作用:

<g:textField name="books[0].title" value="the Stand" /> 
<g:textField name="books[1].title" value="the Shining" /> 
<g:textField name="books[2].title" value="Red Madder" /> 
然后Grails将自动创建 在已定义的位置为您创建一个新实例 位置。如果你“跳过”了一些 元素在中间…然后是圣杯 将在中自动创建实例 中间


我意识到特定的解决方案可以作为命令对象的一部分或特定控制器的一部分进行设计-但是,在我的应用程序中,在多个域对象中,以及在许多不同类型的对象之间的关联中,对该功能的需求反复出现。因此,一个普遍的解决方案将是理想的。有人知道Grails中是否包含类似的内容吗?

我自己刚刚开始学习Grails,并将您的问题视为一个有趣的研究练习。我认为您不能使用传统的数据绑定机制,因为它在幕后使用某种惰性映射来填补空白。因此,为了实现您的目标,您的“保存”方法(或者它是一个函数?)不太可能包含以下内容:

def Book = new Book(params)
您需要一种机制来修改控制器的“保存”方法

经过一些研究,我了解到您可以修改脚手架模板,该模板负责生成控制器代码或运行时方法。通过运行“Grails安装模板”,可以获得Grails使用的所有模板的副本,并且需要修改的模板文件名为“Controller.groovy

因此,理论上,您可以通过这种方式修改整个应用程序的“save”方法

太好了!您可能认为现在需要做的就是修改模板中的save方法,以便它在params映射中遍历对象条目(例如books),边保存边删除


然而,我认为你所需要的解决方案仍然很难实现。我的直觉告诉我,你所建议的机制是个坏主意的原因有很多

出于一个原因,在我的脑海里,想象一下你有一个分页的书单。这是否意味着您的“保存”可以删除除当前可见页面之外的整个数据库表?好的,让我们假设您设法计算出每页上显示了多少项,如果列表已排序,因此不再按数字顺序-您现在删除什么

也许表单中的多个提交按钮是更好的方法(例如保存更改、添加、删除)。我没有在Grails中尝试过这种方法,但了解应该可以帮助您实现多个提交按钮。我确实曾经在Struts中做过这种事情


HTH

我自己也遇到了这个问题。这很容易解决。Grails使用java.util.Set来表示列表。您可以使用该方法擦除数据,然后添加所需的数据

//clear all documents
bidRequest.documents.clear()

//add the selected ones back
params.documentId.each() {
    def Document document = Document.get(it)
    bidRequest.documents.add(document)
    log.debug("in associateDocuments: added " + document)
};

//try to save the changes
if (!bidRequest.save(flush: true)) {
    return error()
} else {
    flash.message = "Successfully associated documents"
}

我打赌,如果您不想“清除()”所有数据,可以使用“remove()”方法来做同样的事情

我只是遇到了同样的问题

我的应用程序的域非常简单:它有存根对象,存根对象与头对象有很多关系。由于头对象没有自己的生命周期,它们完全由存根控制器和视图管理

域类定义:

class Stub {
List headers = new ArrayList(); 
static hasMany = [headers:Header]
static mapping = {headers lazy: false}
}

class Header {
String value
static belongsTo = Stub     
}
我尝试过“clear and bind”方法,但最终结果是“clear”对象留在数据库中,grails只会为未从关系中删除的对象创建新实例。从用户的角度来看,它确实可以工作,但它会在数据库中留下大量垃圾对象

控制器的update()方法中的代码是:

stubInstance.headers.clear()
stubInstance.properties = params
例如:编辑此关系的-多方面时,我有(对于id=1的给定存根):

删除标题“one”并保存存根对象后,数据库将具有标题:

id=1;value="zero"
id=2;value="one"
id=3;value"two"
id=4;value="zero"
id=5;value="two"
存根对象现在将与id=4和id=5的头关联

此外,在不清除列表的情况下,如果提交的request.headers列表中没有索引,那么数据绑定grails将保持该位置的现有对象不变

我想到的解决方案是绑定数据,然后检查存根的头以查找提交列表中不存在的元素,并将其删除

这看起来是一个非常简单的场景,难道没有任何内置的功能来解决它吗? 必须编写自己的同步逻辑来维护关系,这有点过分了,特别是当grails本身造成了使它变得不平凡的怪癖时


关于删除,clear()元素不应该从数据库中消失吗?我是否在关系或域对象定义中遗漏了某些内容?

有关使用GORM删除子对象集合的详细说明,请参阅本博文的删除子对象部分-

建议阅读本系列的第1部分和第3部分

class Stub {
  List headers = new ArrayList(); 
  static hasMany = [headers:Header]
  static mapping = {
  headers lazy: false
  **headers cascade: "all-delete-orphan"**
   }
  }

class Header {
    String value
    static belongsTo = Stub     
 }
我已经在关系的拥有方添加了cascade属性,现在如果您尝试保存存根,则需要
id=1;value="zero"
id=2;value="one"
id=3;value"two"
id=4;value="zero"
id=5;value="two"
class Stub {
  List headers = new ArrayList(); 
  static hasMany = [headers:Header]
  static mapping = {
  headers lazy: false
  **headers cascade: "all-delete-orphan"**
   }
  }

class Header {
    String value
    static belongsTo = Stub     
 }
def author = Author.findByName("Stephen King")

def book = author.books.find { it.title = 'The Stand' }

author.removeFromBooks(book)