gpt4 book ai didi

grails - grails 2.4.4:如何在服务方法中立即提交每个插入(也称为保存)?

转载 作者:行者123 更新时间:2023-12-02 14:31:23 27 4
gpt4 key购买 nike

  • 如果我声明一个方法是非事务性的,那么我保存一条记录,做一些事情,保存另一条记录,即使第二次保存失败并引发异常,也将提交第一次保存。
  • 如果从另一个具有事务性的服务方法中调用了NonTransactional服务方法,会发生什么?现在它是否成为外部事务的一部分,因此,如果SomeOtherdomainObject()。save()失败,则第一个对象将回滚?

  • 例如。
    @Transactional
    class SomeService {
    @NotTransactional
    def someMethod() {
    new SomeDomainObject().save(failOnError:true, flush:true)
    // do stuff, possibly throw a RuntimeException
    new SomeOtherdomainObject().save(failOnError:true)
    // do more stuff, possibly throw a RuntimeException
    }
    }

    因此被调用(在非事务调用的情况下):
    class SomeControler{
    def someService
    def someControllerMethod() {
    someService.someMethod()
    }
    }

    最佳答案

    据我所知:

  • 是的。
  • 是的。

  • 为什么不设置一些集成测试来确认这一点(并让我们知道结果)?有 a good guide here。注意,为了测试事务功能,需要使测试类成为非事务性的。我链接到的示例页面使用JUnit,但是这里有一些Spock代码可以满足您的需求。
    // MyDomainObject.groovy
    class MyDomainObject {
    String details

    static constraints = {
    // this is default anyway, but I want to make it obvious
    // not setting details and then calling save will cause an exception if
    // save's failOnError is true
    details nullable: false
    }
    }

    // MyService.groovy
    class MyService {
    // only make methods transactional when we explicitly want them to be
    static transactional = false

    // create 2 objects and save, 1st should save ok and second should fail
    def nonTransactionalDoubleSave() {
    def objA = new MyDomainObject()
    objA.details = "This should save ok"
    objA.save(flush: true, failOnError: true)

    def objB = new MyDomainObject()
    objB.details = null // null by default, but I'm just making the point
    objB.save(flush: true, failOnError: true) // this will trigger an exception
    }

    def nonTransactionalSingleSave() {
    def objA = new MyDomainObject()
    objA.details = "This should save ok"
    objA.save(flush: true, failOnError: true)
    }

    @Transactional
    def transactionalSave() {
    nonTransactionalSingleSave() // this should create 1 object
    // this should create 2 objects, but the 2nd will trigger an exception and rollback the transaction, meaning there should be no objects in the DB
    nonTransactionalDoubleSave()
    }
    }


    import spock.lang.*
    import grails.test.spock.*

    class MyServiceIntegrationSpec extends IntegrationSpec {
    static transactional = false // the test case must not be transactional

    def myService = new MyService()

    def setup() {
    // remove all my domain objects from the database that might be in there
    MyDomainObject.where{}.deleteAll()
    }

    def cleanup() {
    // remove all my domain objects from the database that a test may have created
    MyDomainObject.where{}.deleteAll()
    }

    def "Question 1: nonTransactionalDoubleSave should create 1 object only"() {
    expect: "a clean database"
    MyDomainObject.count() == 0

    when: "nonTransactionalDoubleSave is called"
    myService.nonTransactionalDoubleSave()

    then: "we get an exception but still get one object in the database"
    thrown(Exception)
    MyDomainObject.count() == 1
    def obj = MyDomainObject.list().getAt(0)
    obj.details = "This should save ok"
    }

    def "Question 2: transactionalSave should create no objects"() {
    expect: "a clean database"
    MyDomainObject.count() == 0

    when: "transactionalSave is called"
    myService.transactionalSave()

    then: "we get an exception and no objects in the database"
    thrown(Exception)
    MyDomainObject.count() == 0
    }

    }

    关于grails - grails 2.4.4:如何在服务方法中立即提交每个插入(也称为保存)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28815503/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com