Grails团队不赞成在控制器中编写核心业务逻辑,因为这不利于代码的重用。事务层,就是用来编写核心业务逻辑的地方。
创建事务Service类的命令:
grails create-service helloworld.simple
说明:helloworld是包名,如果没有明确指定包名,那么默认会选择程序名作为包名
命令执行成功后,生成文件所在位置:
grails-app/services/helloworld/SimpleService.groovy
事务,通常用于处理多个模型domain之间的逻辑关系,也常常会涉及到大范围的持久化操作(将数据库保存至数据库)
关闭事务的配置:
class CountryService {
static transactional = false
}
#################
import org.springframework.transaction.annotation.Transactional
class BookService {
@Transactional(readOnly = true)
def listBooks() {
Book.list()//写在控制器中
}
@Transactional
def updateBook() {
// …
}
def deleteBook() {
// …
}
}
#############
事务回滚以及会话:
class Author {
String name
Integer age
static hasMany = [books: Book]
}
Author.withTransaction { status ->
new Author(name: "吕常龙", age: 99).save(flush: true) //可简单理解为,保存成功
status.setRollbackOnly() //事务回滚,取消保存操作
}
Author.withTransaction { status ->
new Author(name: "深思君", age: 99).save(flush: true) //保存成功
}
#############
事务的开发:
class AuthorService {
void updateAge(id, int age) {
def author = Author.get(id)
author.age = age
if (author.isTooOld()) {
throw new AuthorException("too old", author)
}
}
}
事务的应用:
class AuthorController {
def authorService //依赖注入,映射着AuthorService,可简单理解为def authorService = new AuthorService()
def updateAge() {
try {
authorService.updateAge(params.id, params.int("age"))
}
catch(e) {
render "Author books ${e.author.books}"
}
}
}
class AuthorController {
AuthorService authorService
def updateAge() {
try {
authorService.updateAge(params.id, params.int("age"))
}
catch(e) {
flash.message = "Can't update age"
redirect action:"show", id:params.id
}
}
}
class AuthorController {
def authorService
def updateAge() {
try {
authorService.updateAge(params.id, params.int("age"))
}
catch(e) {
def author = Author.read(params.id)
render "Author books ${author.books}"
}
}
}
###############
错误验证与回滚
import grails.validation.ValidationException
class AuthorService {
void updateAge(id, int age) {
def author = Author.get(id)
author.age = age
if (!author.validate()) {
throw new ValidationException("Author is not valid", author.errors) //抛出ValidationException异常,自动回滚
}
}
}
import grails.validation.ValidationException
class AuthorController {
def authorService
def updateAge() {
try {
authorService.updateAge(params.id, params.int("age"))
}
catch (ValidationException e) {
def author = Author.read(params.id)
author.errors = e.errors
render view: "edit", model: [author:author]
}
}
}
#############重点开始
实际验证过的例子:
@Transactional
class MyService {
def go() {
def author = new Author(name: "深思君+3")
if(author.save(flush: true)) { //保存成功
throw new Exception("Author is not valid", author.errors) //抛出异常,进行回滚,结果当然是保存失败
} else {
println "保存失败"
}
}
}
class BookController {
def myService
def index() {
try {
myService.go()
} catch (Exception e) {
println "error" + e
}
render "ok" + new Date().format("HH:mm:ss")
}
}
###############重点结束
依赖注入:
class BookController {
def bookService //对应着BookService,首字母小写
…
}
特殊情况处理:
类名前两个字母都是大写的情况下,如JDBCHelperService,则依赖注入名称与类名相同,即JDBCHelperService
class BookController {
def JDBCHelperService //对应着JDBCHelperService,与类名相同
…
}
###############
在Services中实现依赖注入:
class AuthorService {
def bookService
}
在模型domain以及标签库中实现依赖注入:
class Book {
…
def bookService
def buyBook() {
bookService.buyBook(this)
}
}
###############
grails-app/services/bookstore/BookService.groovy
package bookstore
class BookService {
void buyBook(Book book) {
// logic
}
}
本文暂时没有评论,来添加一个吧(●'◡'●)