Отношение Grails "многие ко многим" не работает должным образом
Я новичок в 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
}
}
Вот html-выдержка из формы, которая динамически создается с использованием JS, ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ, ЧТО ВСЕ КОД, КОТОРЫЙ Я ВКЛЮЧИЛ, НЕ ПОЛНЫЙ, ЭТО ПРОСТО ДАЕТ ВАМ ИДЕЮ ТОГО, ЧТО Я ДОЛЖЕН ДОСТИГАТЬ:
<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 & Mrs">Mr & 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")
}
Таким образом, из кода у меня есть родительский домен "Комментарий", который имеет много "GroupComment", который имеет много "Комментарий".
Когда я строю свой проект, моя база данных дает мне следующие таблицы:
comment
comment_comment_groups
comment_group
Что удивило меня, так как я предусмотрел отношения "многие ко многим", так что ожидал:
comment
comment_comment_groups
comment_group_comments
comment_group
Я, вероятно, ожидаю, что Grails сделает слишком много работы здесь. Поэтому, когда я отправляю свои комментарии, база данных заполняется моим родительским "Комментарием", и даже домены "CommentGroup", принадлежащие "Комментарию", но комментарии "CommentGroup" не сохраняются в базе данных.
Я понимаю, что я здесь наивен, но чего мне не хватает? Может ли кто-нибудь помочь, так как я искал высокие и низкие и не может найти похожий сценарий. Я знаю, что существует множество примеров отношений "многие ко многим", но ни один из них не покрывает мой сценарий.
А пока продолжу поиски.
Я предполагаю, что мне нужно создать более сложное действие "сохранить" в моем контроллере, вручную обрабатывая параметры, но было бы хорошо, если бы был способ GORM добиться этого.
С нетерпением жду ответа... пожалуйста, будьте нежны со мной:-)
Заранее спасибо.
1 ответ
Удалите из комментария домен класса commentGroups cascade: "all-delete-orphan" и добавьте в CommentGroup отображение: comments cascade: "all-delete-orphan".
Новый комментарий (params).save() Сохранить группу комментариев со всеми комментариями принадлежит этой группе.