我正在玩grails 3应用。我使用粗体动作创建了这个简单的书本应用程序。它不更新记录。
这是书域
package bookapp
class Book {
String name
static constraints = {
}
}
这是图书管理员
package bookapp
import grails.plugin.springsecurity.annotation.Secured
@Secured('ROLE_USER')
class BookController {
def index() {
[books: Book.findAll()]
}
def create(){
}
def save(){
def book = new Book(params)
book.save()
redirect(action:'show', id:book.id)
}
def edit(Long id){
[book: Book.get(id)]
}
def update(Long id){
def book = Book.get(id)
bindData(book, params)
book.save()
redirect(action:'show', id:book.id)
}
def show(Long id){
[book: Book.get(id)]
}
def destroy(){
}
}
这是编辑视图页面
<h1> Edit Book Page</h1>
<g:form action="update" id="${book.id}">
<g:textField name="name" value="${book.name}"></g:textField>
<g:submitButton name="submit"></g:submitButton>
</g:form>
当我进入编辑页面并更改名称字段,然后单击提交按钮。它不会更新这本书。如果我将更新操作更改为
def update(Long id){
def book = Book.get(id)
bindData(book, params)
book.save(flush:true)
redirect(action:'show', id:book.id)
}
这有效。所以我的问题是为什么我们需要显式刷新?为什么save()不保存记录?我有什么想念的吗?感谢您的帮助!
完整代码:
首先按如下方式创建域图书
class Book {
String name
static constraints = {
}
}
创建Book控制器
class BookController {
def index() {
[books: Book.findAll()]
}
def create(){
}
def save(){
def book = new Book(params)
book.save()
redirect(action:'show', id:book.id)
}
def edit(Long id){
[book: Book.get(id)]
}
def update(Long id){
def book = Book.get(id)
book.properties = params
book.save()
redirect(action:'show', id:book.id)
}
def show(Long id){
[book: Book.get(id)]
}
def destroy(Long id){
Book.get(id).delete()
redirect(action:'index')
}
}
观看次数
create.gsp
<h1> Create Book Page</h1>
<g:form action="save">
<g:textField name="name"></g:textField>
<g:submitButton name="submit"></g:submitButton>
</g:form>
edit.gsp
<h1> Edit Book Page</h1>
<g:form action="update" id="${book.id}">
<g:textField name="name" value="${book.name}"></g:textField>
<g:submitButton name="submit"></g:submitButton>
</g:form>
index.gsp
<g:each in="${books}" var="book">
<h2><g:link action="show" id="${book.id}"> ${book.name} </g:link></h2>
</g:each>
<g:link controller="book" action="create">Create Book</g:link>
show.gsp
<h1> ${book.name} </h1>
<g:link action="edit" id="${book.id}">Edit</g:link>
<g:link action="destroy" id="${book.id}">Delete</g:link>
<g:link action="index">Back</g:link>
删除和更新不适用于仅save()。需要添加save(flush:true)。谢谢!
更新: 这很奇怪。相同的代码适用于grails2。我尝试过grails 2.2。它仅不适用于grails3。我用来测试的grails 3版本是grails 3.3.6。 grails 3是否有任何改变打破了这一点?
更新2:
我现在将删除操作移至服务中,如下所示。
@Transactional
class BookService {
def destroy(Long id) {
def b = Book.get(id)
b.delete()
}
}
在控制器中
class BookController {
def bookService
def destroy(Long id){
bookService.destroy(id)
redirect(action:'index')
}
}
要删除的查看代码是
<h1> ${book.name} </h1>
<g:link action="edit" id="${book.id}">Edit</g:link>
<g:link action="destroy" id="${book.id}">Delete</g:link>
<g:link action="index">Back</g:link>
当我单击“删除”时,它将重定向到索引页面,但我仍然可以看到记录。我有什么想念的吗?谢谢!
答案 0 :(得分:4)
在我曾经使用过的每个Grails应用程序中,我都看到了两个经典错误。因此,不要灰心。
首先,虽然您可以在Controller中进行持久性处理,但您不应该将其用于服务,以使业务逻辑与路由和呈现脱钩。
第二,当您进行数据库修改时,您应该使用事务。在Grails中,您可以使用@Transactional来实现,可以将其添加到方法或类中。通常,除非需要保存的记录的ID,否则不必执行flush:true。 @Transactional可以采用许多参数来更改事务的工作方式: https://docs.grails.org/latest/guide/services.html#declarativeTransactions
前一段时间,我为Grails 3创建了这些架构图: https://github.com/virtualdogbert/Grails_Architecture
我还创建了此页面作为Groovy / Grails资源的位置: https://github.com/virtualdogbert/Groovy_Links
希望有帮助。
对于删除而言,您在服务中的列表设置如下:
class BookService {
@Transactional(readOnly = true)
def listBooks() {
Book.list()
}