0

我正在开发一个企业应用程序,我们在其中使用 Hibernate 以及与连接表的多对多关系。我们在生产中(大量)看到非常零星的数据库死锁,我们无法重新创建。

类别.java

public class Category {
    ....
    private Set<Product> products = new HashSet<Product>();
    ...
}

类别.hbm.xml

<class 
    name="Category"
    table="CATEGORY"
>
    ...
   <!-- uni-directional many-to-many association to Product -->
   <set
       name="products"
       table="CATEGORY_PRODUCT_ASSC"
       lazy="false"
       cascade="none"
    >
        <key column="CATEGORY_ID" />
        <many-to-many class="Product" column="PRODUCT_ID" />
    </set>
</class> 

Product.java、Product.hbm.xml没有一组类别,因为这是单向多对多

CATEGORY_PRODUCT_ASSC表是一个简单的连接表,只有 2 列:CATEGORY_IDPRODUCT_ID.

现在,我们调用Session.saveOrUpdateCategory 实例对象的唯一目的是获取 CATEGORY_PRODUCT_ASSC 连接表中的插入(Category 上没有任何变化)

我打开休眠show_sql并看到以下内容:

update CATEGORY set NAME=?, DESCRIPTION=?, where category_id=?
insert into CATEGORY_PRODUCT_ASSC (CATEGORY_ID, PRODUCT_ID) values (?, ?)

问题是我们在多个服务器上以完全相同的时间创建了许多产品,所有产品都属于同一个类别。

当我们看到死锁时,update CATEGORY不可避免地会涉及到调用。我们需要阻止这些update CATEGORYSQL 语句被执行。

选项1:有什么方法可以调用 Session.saveOrUpdate(category) 并让它不更新 Category (因为它没有改变),但仍然插入连接表 CATEGORY_PRODUCT_ASSC ?

选项 2:如果没有,我们考虑过通过 JDBC 直接插入 CATEGORY_PRODUCT_ASSC 行。然而,一个问题是缓存中陈旧的 Hibernate 对象(Category 对象)。关于这种可能的方法的任何想法/建议?

非常感谢您的帮助。:-)

4

1 回答 1

0

我们解决了这个问题。结果确实是update category声明。我们没有使用该CATEGORY_PRODUCT_ASSC表作为多对多关系的连接,而是创建了一个 Hibernate 管理的实体来表示这个连接表CategoryProductAssc......。

这样,我们可以直接保持关系,而无需调用Session.saveOrUpdateCategory 实例对象,其唯一目的是在CATEGORY_PRODUCT_ASSCCategory 对象上没有任何更改时获取连接表中的插入。

我创建了 Cactus 测试,可以同时执行 20 次,测试旧代码和新代码,我们的 DBA 监控并看到旧代码的并发性,而新代码没有并发性。

于 2012-09-27T02:39:44.287 回答