删除子记录Grails 4时出现Hibernate错误



我很难从关联中删除子项。我使用的是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"
}
}

和购物车项目:

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', 'bigint(20)', 'NO', 'PRI', '', ''
'product_id', 'bigint(20)', 'NO', 'PRI', '', ''
'version', 'bigint(20)', 'NO', '', '', ''
'date_created', 'datetime', 'NO', '', '', ''
'last_updated', 'datetime', 'NO', '', '', ''
'quantity', 'int(11)', 'NO', '', '', ''
'purchase_price', 'decimal(19,2)', 'NO', '', '', ''
'last_item_added', 'datetime', 'NO', '', '', ''

我花了很多时间试图删除一个购物车项目。我已经通读了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的绑定参数为null。我不知道是不是这导致了我的问题,但这似乎是可疑的。当我调试代码时,被删除的cartItem确实引用了parentShopping cart,并且任何对象上的id都不是null,所以我不知道这些null来自哪里。

有什么想法吗?

您是否尝试将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关系(工作得很好。即没有save()问题,只有delete()问题。

最新更新