Grails:执行两个连续事务同时修改同一个对象的最佳方法是什么?

时间:2017-04-30 08:10:54

标签: hibernate grails transactions

在我的服务中,有些资源由用户保留。 当用户结束使用/保留资源时,将调用checkout“controller method”。 在那种方法中,理想情况下应该发生3件事。他们是: 1.资源被释放。 2.调用远程支付服务以根据资源的使用量向用户收费。 3.预订对象标记为已付款。

在这3个步骤中,步骤1应始终发生,步骤2和3仅在一起。

我的问题是如何在代码中理想地处理这个问题? (这里,预留对象对象包含有关资源预留的信息。如果预约的使用已经开始但未结束,那么它将保留引用的资源。) 答:可以/我应该在交易之间分享预订对象吗?要么, B:我应该在每笔交易中单独“获取”预订对象吗? C:在所有交易之外首先获得预订对象是否有难闻的气味? D:我现在正在使用Grails 2.4.4。你的答案会因Grails版本的不同而有所不同吗?我应该升级到更新的版本吗?

以下是代码中的示例(我只获取一次预留对象)。 (当然,事务可能发生在服务中,但使用withNewTransaction方法更容易证明这一点。)。 这是一个好方法,或者下面的代码应该如何改变?

/*Domain class*/
class Reservation {
    Resource resource;
    Date useStarted;
    Date useEnded;
    Boolean charged;
}


class ReservationController {

    def nonTransactionalPaymentService

    def checkout(){
        def reservationId = params.reservationId as Long

        def reservation = Reservation.get(reservationId )
        Reservation.withNewTransaction {
            // reservation = Reservation.get(reservationId ) ??
            reservation.useEnded = new Date()
            reservation.save(failOnError: true)
        }
        Reservation.withNewTransaction {
            // reservation = Reservation.get(reservationId ) ??
            nonTransactionalPaymentService.charge(reservation)
            reservation.charged = true
            reservation.save(failOnError: true) // I'm screwed if this fails
        }
        // rendering code here
    }
 }

我之所以这样问是因为我的代码中有两种现象我还没有完全摆脱: 1.奇怪的异常如:“连接已被放弃PooledConnection”。 2.获取对象时,以前的事务的更改不会立即显示。

1 个答案:

答案 0 :(得分:0)

我发现之间有区别:

def reservation = Reservation.get(reservationId )
Reservation.withNewTransaction {
 ..
}
Reservation.withNewTransaction {
..
}

Reservation.withNewTransaction {
   def reservation = Reservation.get(reservationId )
    // reservation = Reservation.get(reservationId ) ??
    reservation.useEnded = new Date()
    reservation.save(failOnError: true)
}
Reservation.withNewTransaction {
   def reservation = Reservation.get(reservationId )
    // reservation = Reservation.get(reservationId ) ??
    nonTransactionalPaymentService.charge(reservation)
    reservation.charged = true
    reservation.save(failOnError: true) // I'm screwed if this fails
}

召回时的含义 - 重新启动新事务中的对象,然后获取最新更改。

.read .get之间也存在细微变化,如果在整体服务中禁用了交易。看一下queuekit插件中的许多newTransaction内容,试图在任何时候选择最新的更新。