Transaction handling is one of the more complex areas of web development. Anytime a user takes any action in the interface which demands a couple of database actions in the backend, then usually you end up having do it as transaction. For a user, everything is either a success or failure. Partial success may be either harmful to the system or doesn’t mean anything to the user. Grails, since it is built on top of Spring and Hibernate, uses their underlying mechanism to deal with transactions. While it may seem confusing in the beginning, Grails actually makes it even more easier.
Lets see it in code.
Suppose we are designing an Offers System, like the one that your bank sends notifying you of some offers and promotions on services. A simplified object structure may be like the following:
1.
class
Offer {
2.
String title
3.
String content
4.
Date expirationDate
5.
Date createdDate =
new
Date()
6.
7.
static
hasMany = [recipients: Recipient]
8.
}
1.
class
Recipient {
2.
String email
3.
4.
static
belongsTo = [offer: Offer]
5.
}
The relationship is fairly simple. Each Offer can have many Recipients, each Recipient belongs to an Offer.
belongsTo just means the offer Recipient will be deleted whenever the Offer is deleted, which makes sense coz we don’t want to keep the junk if the Offer itself is deleted.
hasMany lets you access to the Recipients from the Offer object. In other words, if you have the Offer object, you can dooffer.recipients and get the list of all the recipients for the Offer. Cool.
Now, here is how it will work. We want to add an Offer and some Recipients. Everything should either succeed or fail. Even if only one Recipient out of thousands fail, everything should fail.
There are two ways to do transactions in Grails:
1. Method-level Transaction: By default, each Service class in grails has a transactional property set to true. So if any public method in a Service class throws a RuntimeException or any Error, the transaction will be rolled back. If you do not need this default transaction property, you can explicitly set transactional to false.
In the code below, the OfferService throws a Runtime Exception anytime it isn’t able to add the Fffer or the Recipient, and the transaction will be rolled back.
You wouldn’t get the same transactional behavior if the method throws any Checked Exception or if the transactionalproperty is set to false.
01.
class
OfferService {
02.
03.
boolean
transactional =
true
04.
05.
def save(offer, recipients) {
06.
if
(!offer.validate()) {
07.
throw
new
RuntimeException(
"Invalid offer."
)
08.
}
else
{
09.
def result = offer.save()
10.
recipients.each {
11.
if
(!it.validate()) {
12.
throw
new
RuntimeException(
"Invalid recipient"
)
13.
}
else
{
14.
offer.addToRecipients(it)
15.
}
16.
}
17.
}
18.
}
19.
}
You can then catch the exception in the Controller and render a more user-friendly error message.
01.
class
OfferController {
相关推荐
import grails.transaction.Transactional @Transactional class UserService { User createUser(String name, String email) { new User(name: name, email: email).save(flush: true) } } ``` ### 9. 插件...
Grails还支持异步查询,利用`withNewSession`或`withTransaction`方法,可以避免阻塞主线程。同时,GORM提供了缓存机制,提升性能。 ### 6. 扩展查询 开发者可以通过扩展GORM的能力来自定义查询,如添加新的查询...
Spring Recipes 3rd Edition Sources === These are the sources belonging to Spring Recipes 3rd Edition. Each chapter has its own sources and each chapter can contain multiple source snippets ...20. Grails
经过测试的功能完备的Spring 3.2参考应用程序,具有JPA持久性,REST Level-3资源,异步处理,作业,安全性,单元,模拟,集成,功能,其余客户端存根,性能测试以及许多最佳实践,聚集了在MVC / Spring / Grails网络...
5. **GORM支持**(Grails Object Relational Mapping):对于使用Groovy on Grails的项目,可能需要`hibernate-gorm-5.2.2.jar`,它为Grails应用提供了基于Hibernate的ORM服务。 6. **其他依赖**:可能还包括如`dom...
根据给定的信息,本文将对Java相关的架构图进行详细的解读与分析,主要涵盖Spring、Hibernate、Struts(包括Struts1和Struts2)、JSF、Seam、Grails、DWR、J2EE、Oracle等技术栈的核心概念及其架构特点。 ### 1. ...
GORM,全称Grails Object Relational Mapping,是Grails框架中的数据持久化工具,它提供了简洁的API,使得开发者可以方便地进行数据库操作,类似于Java的Hibernate或Ruby on Rails的ActiveRecord。GORM不仅支持关系...
Spring Transaction Management 事务管理是保证数据一致性的重要手段,Spring 提供了全面的事务管理功能,可以方便地应用于不同的业务场景中。 #### 12. Spring Batch 对于需要处理大量数据的任务,Spring Batch...
JTA (Java Transaction API) 是Java平台上的事务处理标准。这部分内容详细介绍了如何将Ehcache与JTA结合使用,以支持事务处理。 #### 二十七、搜索(Search) 在某些应用场景下,需要对缓存中的数据进行搜索。这...