Grails 创建后获取域对象的id

Grails 创建后获取域对象的id,grails,gorm,Grails,Gorm,我正在进行结账,当用户进行购买时,将创建一个purchase对象并将其保存到数据库中。然后,我获取对象的id,并将其发送给PayPal以生成一个按钮(这样我以后就可以识别购买)。但是,当我尝试检索id时,它返回null 我在访问id之前尝试过刷新它,但它似乎仍然不起作用 这是我的域对象: package website import java.time.Instant import java.time.temporal.ChronoUnit class Purchase { Stri

我正在进行结账,当用户进行购买时,将创建一个
purchase
对象并将其保存到数据库中。然后,我获取对象的
id
,并将其发送给PayPal以生成一个按钮(这样我以后就可以识别购买)。但是,当我尝试检索id时,它返回null

我在访问id之前尝试过刷新它,但它似乎仍然不起作用

这是我的域对象:

package website

import java.time.Instant
import java.time.temporal.ChronoUnit

class Purchase {
    String buttonId
    final Instant expires
    private boolean complete

    User user
    Product product

    Purchase(Product product, User user) {
        this.product = product
        this.user = user

        expires = Instant.now().plus(1, ChronoUnit.DAYS)
    }

    void completePurchase() {
        // confirm that the purchase hasn't been completed already
        if (complete) {
            throw new PurchaseAlreadyCompleteException()
        }

        complete = true
    }

    boolean isComplete() {
        return complete
    }

    static class ButtonIdAlreadyInitializedException extends RuntimeException {}

    static class PurchaseAlreadyCompleteException extends RuntimeException {}
}
以下是我正在运行的代码:

Purchase purchase = new Purchase(product, user)
purchase.save(flush: true)
println 'purchase id: ' + purchase.id

ID为空,因为未保存对象。未保存该属性的原因是您没有为
按钮ID
赋值,并且该属性是必需的。您可以通过以下方式进行验证:

Purchase purchase = new Purchase(product, user)
purchase.save(flush: true, failOnError: true) // will throw an exception if saving fails
println 'purchase id: ' + purchase.id

ID为空,因为未保存对象。未保存该属性的原因是您没有为
按钮ID
赋值,并且该属性是必需的。您可以通过以下方式进行验证:

Purchase purchase = new Purchase(product, user)
purchase.save(flush: true, failOnError: true) // will throw an exception if saving fails
println 'purchase id: ' + purchase.id

您需要捕获purchase.save()方法的结果。它返回更新的域对象,其中包含已解析的id。因此,您的代码应该如下所示:

Purchase purchase = new Purchase(product, user)
purchase = purchase.save(flush: true)
if (!purchase || purchase.hasErrors()) {
    log.error("Failed to commit purchase - probable validation errors')
}
println 'purchase id: ' + purchase.id
请注意,如果在save方法中设置failOnError:true标志,那么如果存在阻止保存该方法的验证或hibernate/SQL错误,它将引发异常。我发现我比上面提供的软检查更喜欢异常处理


此外,由于域定义中没有约束块,所有字段都将为空:默认情况下为false,因此您必须为buttonId提供一个值,否则域将无法验证,purchase.save()方法调用将失败。

您需要捕获purchase.save()方法的结果。它返回更新的域对象,其中包含已解析的id。因此,您的代码应该如下所示:

Purchase purchase = new Purchase(product, user)
purchase = purchase.save(flush: true)
if (!purchase || purchase.hasErrors()) {
    log.error("Failed to commit purchase - probable validation errors')
}
println 'purchase id: ' + purchase.id
请注意,如果在save方法中设置failOnError:true标志,那么如果存在阻止保存该方法的验证或hibernate/SQL错误,它将引发异常。我发现我比上面提供的软检查更喜欢异常处理


此外,由于域定义中没有约束块,所有字段都将为空:默认为false,因此必须为buttonId提供一个值,否则域将无法验证,purchase.save()方法调用将失败。

从设计角度来看,最好使用单独的序列作为提供PayPal的业务密钥。您不应该与第三方共享数据的主键。可能您在保存时出错。如果有错误,可以使用
save(failOnError:true)
抛出错误。从设计角度来看,最好使用单独的序列作为提供PayPal的业务密钥。您不应该与第三方共享数据的主键。可能您在保存时出错。如果有错误,可以使用
save(failOnError:true)
抛出错误。