Grails 多对多关系未按预期工作

Grails Many-to-Many relationship not working as expected

我是一个 Grails 新手,面临着一个棘手的多对多关系问题。

这里是域名 类 简化版:

class Comment {
    String title
    String comment

    static hasMany = [commentGroups:CommentGroup]

    static constraints = {
        title blank:true
        comment blank:false, maxSize:800
    }

    static mapping = {
        commentGroups cascade: "all-delete-orphan"
    }

}

class CommentGroup {

    String groupTitle

    static hasMany = [comments:Comment]
    static belongsTo = Comment

    static constraints = {
        groupTitle blank:true, nullable:true
    }
}

这是使用 JS 动态构建的表单的 html 摘录,请注意,我包含的所有代码并不完整,它只是为了让您了解我需要实现的目标:

<form class="m-b-d" role="form" name="comments" id="comments" method="post" action="/rootstofood/comment/save">



  <div class="form-group has-feedback col-sm-12">
    <label for="rating" class="control-label">Give us a star rating?</label>
    <div class="br-wrapper br-theme-bootstrap-stars">
      <select aria-describedby="Rating" name="rating" id="rating" class="form-control input-lg" style="display: none;">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
      </select>
      <div class="br-widget"><a href="#" data-rating-value="1" data-rating-text="1"><span></span></a><a href="#" data-rating-value="2" data-rating-text="2"><span></span></a><a href="#" data-rating-value="3" data-rating-text="3"><span></span></a><a href="#" data-rating-value="4"
        data-rating-text="4"><span></span></a><a href="#" data-rating-value="5" data-rating-text="5"><span></span></a>
        <div class="br-current-rating"></div>
      </div>
    </div>
  </div>

  <div class="form-group has-feedback col-sm-12">
    <label for="commentTitle" class="control-label sr-only">Any short comment header?</label>
    <input aria-describedby="Comment title" placeholder="Any short comment header?" value="" id="commentTitle" name="commentTitle" class="form-control input-lg" maxlength="200">
    <span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
    <span class="sr-only" id="commentTitle">(success)</span>
  </div>

  <div class="form-group has-feedback col-sm-12">
    <label for="startComment" class="control-label sr-only">Start comment</label>
    <textarea rows="3" aria-describedby="Start comment" placeholder="Enter start comment" id="startComment" name="startComment" class="form-control input-lg vrequired" maxlength="400"></textarea>
    <span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
    <span class="sr-only" id="startComment">(success)</span>
  </div>

  <!-- Children or staff comments area START -->

  <!-- ##### Dynamic area START #### -->
  <div class="col-sm-12" id="comment-groups">

    <div class="panel panel-default p-trbl" data-group-id="0" id="comment-group-0" data-remove-group-id="0">
      <div class="ovh">
        <div class="pull-left"><b>Comment Group: 0</b>
        </div><a class="danger pull-right remove-comment-group" data-remove-group-id="0" href="#"><span class="glyphicon glyphicon-remove-sign"></span> Remove</a>
      </div>
      <div class="panel-body">

        <div class="form-group has-feedback col-sm-12">
          <label for="title" class="control-label sr-only">Any short comment header?</label>
          <input aria-describedby="Comment Group title" placeholder="Any short comment group header?" value="" name="commentGroups[0].groupTitle" class="form-control input-lg" maxlength="200">
          <span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
          <span class="sr-only" id="title">(success)</span>
        </div>

        <!-- Children or staff comments area START -->
        <div class="col-sm-12" data-comments-group-id="0" id="comments">

          <div class="panel panel-default p-trbl" data-comment-group-id="GROUP" id="comment-0_0">
            <div class="ovh">
              <div class="pull-left"><b>Staff/Pupil Group/Comment: 0</b>
              </div><a class="danger pull-right remove-comment" data-remove-comment-id="0_0" href="#"><span class="glyphicon glyphicon-remove-sign"></span> Remove</a>
            </div>
            <div class="panel-body">
              <div class="form-group has-feedback col-sm-12">
                <label for="startComment" class="control-label sr-only">Comment</label>
                <textarea id="commentGroups[0].comments[0].startComment" rows="3" aria-describedby="Comment" placeholder="Enter comment" name="commentGroups[0].comments[0].startComment" class="form-control input-lg vrequired" maxlength="400"></textarea>
                <span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
                <span class="sr-only" id="comment">(success)</span>
              </div>
              <div class="form-group has-feedback col-sm-10">
                <label for="name" class="control-label sr-only">Name</label>
                <input type="text" aria-describedby="Name" placeholder="Name" name="commentGroups[0].comments[0].name" class="form-control input-lg vrequired" maxlength="30">
                <span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
                <span class="sr-only" id="name">(success)</span>
              </div>
              <div class="form-group has-feedback col-sm-2">
                <label for="type" class="control-label sr-only">Comment from</label>
                <select aria-describedby="Type" name="commentGroups[0].comments[0].type" id="type" class="form-control input-lg">
                  <option value="Parent">Parent</option>
                  <option value="Pupil">Pupil</option>
                  <option value="Staff">Staff</option>
                  <option value="KS1">KS1</option>
                  <option value="KS2">KS2</option>
                  <option value="Other">Other</option>
                </select>
              </div>
            </div>
          </div>
        </div>
        <div class="form-group has-feedback col-sm-12">
          <a data-comment-group-id="0" class="add-comment success" href="#"><span class="glyphicon glyphicon-plus-sign"></span> Add another pupil or staff comment</a>
        </div>
        <!-- Children or staff comments area END -->

      </div>
    </div>
  </div>

  <div class="form-group has-feedback col-sm-12">
    <a class="add-group success" href="#"><span class="glyphicon glyphicon-plus-sign"></span> Add another comment group</a>
  </div>

  <!-- Children or staff comments area END -->

  <div class="form-group has-feedback col-sm-12">
    <label for="endComment" class="control-label sr-only">End comment</label>
    <textarea rows="3" aria-describedby="End comment" placeholder="Enter end comment" id="endComment" name="endComment" class="form-control input-lg" maxlength="400"></textarea>
    <span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
    <span class="sr-only" id="endComment">(success)</span>
  </div>

  <div class="form-group has-feedback col-sm-2">
    <label for="title" class="control-label sr-only">Title</label>
    <select aria-describedby="Title" name="title" id="title" class="form-control input-lg">
      <option value="Mr">Mr</option>
      <option value="Mrs">Mrs</option>
      <option value="Ms">Ms</option>
      <option value="Miss">Miss</option>
      <option value="Mr &amp; Mrs">Mr &amp; Mrs</option>
    </select>
  </div>

  <div class="form-group has-feedback col-sm-10">
    <label for="firstName" class="control-label sr-only">Name</label>
    <input type="text" aria-describedby="Name" placeholder="Name" id="name" name="name" class="form-control input-lg vrequired" maxlength="60">
    <span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
    <span class="sr-only" id="Name">(success)</span>
  </div>

  <div class="form-group has-feedback col-sm-12">
    <label for="jobTitle" class="control-label sr-only">Job title</label>
    <input type="text" aria-describedby="Job title" placeholder="Job title" id="jobTitle" name="jobTitle" class="form-control input-lg" maxlength="60">
    <span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
    <span class="sr-only" id="jobTitle">(success)</span>
  </div>

  <div class="form-group has-feedback col-sm-12">
    <label for="organisation" class="control-label sr-only">Organisation</label>
    <input type="text" aria-describedby="Organisation" placeholder="Organisation" id="organisation" name="organisation" class="form-control input-lg" maxlength="60">
    <span aria-hidden="true" class="glyphicon glyphicon-ok form-control-feedback hidden"></span>
    <span class="sr-only" id="organisation">(success)</span>
  </div>

  <div class="form-group has-feedback col-sm-2">
    <label for="type" class="control-label sr-only">Type</label>
    <select aria-describedby="Type" name="type" id="type" class="form-control input-lg">
      <option value="Parent">Parent</option>
      <option value="Pupil">Pupil</option>
      <option value="Staff">Staff</option>
      <option value="KS1">KS1</option>
      <option value="KS2">KS2</option>
      <option value="Other">Other</option>
    </select>
  </div>



  <div class="col-md-12">
    <button class="btn btn-default btn-lg onWht" id="feedback" type="submit"><b>Submit Feedback <span class="glyphicon glyphicon-chevron-right"></span></b>
    </button>
  </div>

</form>

这是我不完整的控制器保存操作,几乎是开箱即用的:

    def save() {
        def commentInstance = new Comment(params)

        if (!commentInstance.save(flush: true)) {
            render(view: "index", model: [commentInstance: commentInstance])
            return
        }
        render(view: "thankyou")
}

所以从代码中我有一个父域 'Comment' 有很多 'GroupComment' 有很多 'Comment'.

当我构建我的项目时,我的数据库为我提供了下表:

comment
comment_comment_groups
comment_group

这让我感到惊讶,因为我已经规定了一个多对多关系,所以期待:

comment
comment_comment_groups
comment_group_comments
comment_group

我可能期望 Grails 在这里做太多工作。因此,当我提交我的评论表单时,数据库中填充了我的父 'Comment' 甚至属于 'Comment' 的 'CommentGroup' 域,但 'CommentGroup' 评论不会保存到数据库。

我意识到我在这里很天真,但我错过了什么?任何人都可以提供帮助,因为我已经搜索了高低并且找不到类似的场景。我知道有很多多对多关系示例,但 none 涵盖了我的场景。

同时我会继续搜索。

我的猜测是我需要通过手动处理参数在我的控制器中构建一个更复杂的 'save' 操作,但如果有 GORM 方法来实现它会更好。

期待一些答案...请对我温柔点:-)

提前致谢。

从评论域中删除 class 评论组级联:"all-delete-orphan" 并添加 CommentGroup 映射: comments cascade: "all-delete-orphan".

new Comment(params).save() 保存评论组,所有评论都属于这个组。