0

我将 grails 1.3.7 与 Oracle 11g 一起使用并尝试管理内部事务。我有一个 bean Person,它被传递给进行一些修改的事务(Propagation.REQUIRED)服务方法。然后将其传递给另一个事务性(propagation = Propagation.REQUIRES_NEW)方法,该方法进行一些其他修改,然后引发异常。我期望看到的是对第二个服务的所有修改的回滚,但对第一个服务的修改仍然有效。这是这种情况:

//outer transaction
class MyService {

    def nestedService

    @Transactional(propagation = Propagation.REQUIRED)
    public void testRequiredWithError(Person person) {
        person.name = 'Mark'
        try {
            nestedService.testRequiresNewWithError(person)
        } catch (RuntimeException e) {
            println person.age //this prints 15
            println e
        }
    }
}//end MyService

//inner transaction
class NestedService{

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void testRequiresNewWithError(Person person) {
        person.age = 15 //expected after Exception will be discarded
        throw new RuntimeException("Rollback this transaction!")
    }
}

然后我运行 grails 控制台并在它结束后检查数据库。...

 def p = Person.get(671)
    def myService = ctx.myService 

    println p.name //'John'...from DB
    println p.age  //25...from DB

    myService .testRequiredWithError(p)

    println p.name // 'Mark'....correct
    println p.age  //  15....UNEXPECTED..
    //same result checking on the DB after console ends and transaction flushes

我尝试在引导程序中激活它后使用 Propagation.NESTEDtransactionManager.setNestedTransactionAllowed(true)并使用保存点,如这篇文章 grails transaction set savepoint 但仍然得到相同的结果。

我错过了什么????

先感谢您。

4

2 回答 2

1

我参加聚会有点晚了,但如果您还没有找到答案,我想我知道您为什么会遇到交易问题。

我查看了您关于保存点问题的讨论的链接。根据该讨论,您使用 MySQL 作为数据源。MySQL 默认不支持事务,为了做到这一点,您需要以特殊方式创建表。我在下面提供了一个链接,解释了当你想使用事务时应该如何在 MySQL 中创建表:

http://www.tutorialspoint.com/mysql/mysql-transactions.htm

编辑:本文建议将表的类型设置为 InnoDB 以支持事务。这是一个看起来像的例子:

mysql> create table tcount_tbl
    -> (
    -> tutorial_author varchar(40) NOT NULL,
    -> tutorial_count  INT
    -> ) TYPE=InnoDB;

可能值得注意的是,这不是唯一支持事务的类型,但却是最常见的类型。MySQL 5.5 和更高版本应该自动创建类型为 InnoDB 的表。

希望这可以帮助!

于 2016-05-17T13:04:46.087 回答
0

我将测试p.isAttached()事务回滚将域对象与 Hibernate 会话分离。同样在测试中,我将从数据库中重新加载域对象 -p = Person.get(671)再次有效地从数据库中重新加载数据。

我认为age测试后属性设置为 15 的原因是在异常之后域对象和数据库不同步(并且域对象被分离)。

有关更多信息,请参阅:https ://weblogs.java.net/blog/blog/davidvc/archive2007/04/jpa_and_rollbac.html

于 2015-08-04T12:19:57.227 回答