休眠错误删除子记录 Grails 4

问题描述

我很难将孩子从协会中删除。我正在使用 Grails 4.0.3。 有问题的两个类如下:

购物车:

class ShoppingCart implements Serializable {

    private static final long serialVersionUID = 1

    long id //don't think this is needed since I have a composite id below
    User user
    Store store

    SortedSet<ShoppingCartItem> items
    static hasMany = [items: ShoppingCartItem]

    static constraints = {
        user nullable: false
        store nullable: false
    }

    static mapping = {
        id composite: ['user','store']
        items cascade: "all-delete-orphan"
    }
}

和 ShoppingCartItem:

class ShoppingCartItem implements Comparable<ShoppingCartItem>,Serializable {

    private static final long serialVersionUID = 1

    long id //don't think this is needed since I have a composite id below

    static belongsTo = [shoppingCart: ShoppingCart]

    Product product
    int quantity = 0
    BigDecimal purchasePrice

    Date lastItemAdded

    static constraints = {
        product nullable: false
        purchasePrice nullable: false
        lastItemAdded nullable: false
    }

    static mapping = {
        id composite: ['shoppingCart','product']
    }

    int compareto(ShoppingCartItem otherItem) {
        lastItemAdded.compareto(otherItem.lastItemAdded)
    }
}

因为我有一个双向关系(在 ShoppingCartItem 中使用belongsTo)并且ShoppingCart 有一个复合键,所以我的shopping_cart_item 表如下所示:

'shopping_cart_user_id','bigint(20)','NO','PRI','',''
'shopping_cart_store_id',''
'product_id',''
'version',''
'date_created','datetime',''
'last_updated',''
'quantity','int(11)',''
'purchase_price','decimal(19,2)',''
'last_item_added',''

我有很多时间试图删除购物车项目。我已将 https://spring.io/blog/2010/07/02/gorm-gotchas-part-2/ 通读了好几遍,这对我来说很有意义,但我没有成功。

在 grails 服务方法中,我正在执行以下操作:

def updateCountInCartForProduct(ShoppingCart cart,Serializable productId,int newQuantity) {
        def product = productService.get(productId)
        def cartItem = cart.items.find { it.product == product }
        if ( cartItem ) {
            if ( newQuantity == 0 ) {
                cart.removeFromItems(cartItem) // <-- this line throws the error
              } else {
                cartItem.quantity = newQuantity
                cartItem.save()
            }
        }
    }

执行此方法后,我收到以下错误

12/22/2020 07:48:00 - ERROR [org.hibernate.internal.ExceptionMapperStandardImpl]: HHH000346: Error during managed flush [Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1]
12/22/2020 07:48:01 - ERROR [org.grails.web.errors.GrailsExceptionResolver]: StaleStateException occurred when processing request: [POST] /shop/updateCartQuantity - parameters:
productId: 7
newQuantity: 0
Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1. Stacktrace follows:
java.lang.reflect.InvocationTargetException: null
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

打开 sql 日志记录后,我看到一些对我来说似乎很奇怪的东西:

12/22/2020 07:48:00 - DEBUG [org.hibernate.sql]: delete from shopping_cart_item where shopping_cart_user_id=? and shopping_cart_store_id=? and product_id=? and version=?
12/22/2020 07:48:00 - TRACE [org.hibernate.type.descriptor.sql.BasicBinder]: binding parameter [1] as [BIGINT] - [null]
12/22/2020 07:48:00 - TRACE [org.hibernate.type.descriptor.sql.BasicBinder]: binding parameter [2] as [BIGINT] - [null]
12/22/2020 07:48:00 - TRACE [org.hibernate.type.descriptor.sql.BasicBinder]: binding parameter [3] as [BIGINT] - [7]
12/22/2020 07:48:00 - TRACE [org.hibernate.type.descriptor.sql.BasicBinder]: binding parameter [4] as [BIGINT] - [1]

请注意,shopping_cart_user_id 和shopping_cart_store_id 的绑定参数为空。我不知道这是否是我的问题的原因,但似乎很可疑。当我调试代码时,被删除的 carItem 确实引用了 parentShopping 购物车,并且任何对象上的 id 都不为空,所以我不知道这些空值来自哪里。

有什么想法吗?

解决方法

您是否尝试将 Hibernate 更新到最新版本?如果是这样,并且您仍然遇到问题,请在问题跟踪器 (https://hibernate.atlassian.net) 中创建一个问题,并使用重现问题的测试用例 (https://github.com/hibernate/hibernate-test-case-templates/blob/master/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/JPAUnitTestCase.java)。

,

我在删除与此类似的 1:M 关系时遇到了巨大的问题。我做了各种各样的 removeFromdelete,最后都变成了一个大空头。

解决方案是使用 @Transactional(来自 grails.gorm.transactions.Transactional)显式注释服务方法。它神奇地让一切都像宣传的那样工作,级联等等。

服务类使用 @Service 进行注释。我错误地认为它暗示了 @Transactional,因为默认情况下服务是事务性的,但这并不那么简单。此外,在没有对服务方法进行显式 @Transactional 注释的情况下,创建这些结构(几个 1:M 关系)也能正常工作。 IE。没有save()问题,只有delete()