0

让我们先设置问题。

我拥有的是 >4 表:客户、地址、订单、订单项。每个都使用 Hibernate Annotations 进行映射,并通过 Spring DAO/Services 层访问。

我想要做的是将重复的客户合并在一起。因此,真正需要发生的只是与客户 B 关联的所有订单和地址,需要更新其 customer_id 外键以指向客户 A。然后客户 B 必须设置其禁用位。

hibernate 没有将这些简单的查询发送到我们的数据库,而是发疯了,发出了大量的选择然后更新查询。特别是它选择附加到订单的所有订单项目(因为这是定义EAGER的,并且这一点是不可更改的。)。为了在更新之前获得选择以停止发生,我尝试在常规顶部添加休眠实体注释,javax.persistence.Entity例如:

@org.hibernate.annotations.Entity(dynamicUpdate = true, selectBeforeUpdate = false, dynamicInsert = true)

这似乎没有影响,除了简单的查询,它只更新表中的单个项目。

我使用以下休眠条件获取对象:

            Criteria c1 = null;
            Criteria c2 = null;
            Criteria c = session.createCriteria(Customer.class);
            c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

            if(resultLimit>0) c.setMaxResults(resultLimit);
            if(timeout>0) c.setTimeout(timeout);
            for(String filter: sqlFilters) {
                if(filter.indexOf("{alias}.customer_")!=-1) c.add(Restrictions.sqlRestriction(filter));
                else if(filter.indexOf("{alias}.address_")!=-1 && addrsAttached) {
                    if(c1==null)
                        c1 = c.createCriteria("addresses").setFetchMode("type", FetchMode.JOIN);
                    c1.add(Restrictions.sqlRestriction(filter));
                } else if(filter.indexOf("{alias}.order_")!=-1 && ordersAttached) {
                    if(c2==null)
                        c2 = c.createCriteria("orders").setFetchMode("orderItems", FetchMode.SELECT);
                    c2.add(Restrictions.sqlRestriction(filter));
                }
            }
            return (List<Customer>) c.list();

然后我将所有地址和订单对象从客户 B 移动到客户 A 并运行

return (Customer) this.getHibernateTemplate().merge(customer);

在两个客户对象上。这最终会创建大量获取所有关联对象(即 OrderItems、Products、ProductType、ProductPricingTmpl 等)的 select 语句。

我需要删除这些选择!如果他们不在那里,查询看起来很正常并且很有效率!更新输出的查询是完美且动态的。

有任何想法吗?

4

1 回答 1

2

线索可能在于您选择的 merge() 操作。从休眠 javadoc:

将给定对象的状态复制到具有相同标识符的持久对象上。如果当前没有与会话关联的持久实例,它将被加载。

所以你强迫 Hibernate 在修改它之前加载所有数据。

尝试不同的操作,例如 update() :

使用给定分离实例的标识符更新持久实例。

但是,没有任何承诺,Hibernate 可能会决定无论如何都需要加载它。dynamicUpdates=true 配置实际上可能会使情况变得更糟,因为它需要知道要开始什么才能发布动态更新。

于 2009-06-17T21:12:39.113 回答