Hacer que Hibernate haga actualizaciones simples, en lugar de una enorme selección y actualizaciones

StackOverflow https://stackoverflow.com/questions/1009504

Pregunta

Vamos a configurar la pregunta primero.

Lo que tengo son > 4 tablas: Cliente, Dirección, Pedido, Artículos de pedido. Cada uno se asigna mediante Anotaciones de Hibernate y se accede a través de una capa Spring DAO / Services.

Lo que intento hacer es fusionar clientes duplicados. Entonces, todo lo que realmente necesita suceder es que todos los pedidos y direcciones asociados con el cliente B, necesiten actualizar su clave externa customer_id para apuntar al cliente A. Luego, el cliente B debe tener su bit deshabilitado establecido.

En lugar de enviar estas consultas simples a nuestra base de datos, hibernate se vuelve loco y emite una tonelada de consultas de selección y actualización. En particular, selecciona todos los artículos de pedido adjuntos a un pedido (porque esto se define EAGER y este punto no se puede cambiar). Para obtener las selecciones antes de que la actualización deje de suceder, intenté agregar la anotación de entidad de hibernación en la parte superior del javax.persistence.Entity normal como:

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

esto parecía no tener ningún efecto, excepto con consultas simples donde solo actualizaba elementos individuales en una tabla.

Obtengo los objetos usando los siguientes criterios de hibernación:

            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();

Luego muevo todas las direcciones y objetos de pedido del cliente B al cliente A y ejecuto un

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

en ambos objetos del cliente. Esto termina creando un montón de sentencias select que obtienen todos los objetos asociados (es decir, Artículos de pedido, Productos, Tipo de producto, ProductPricingTmpl, etc.)

¡Necesito eliminar estas selecciones! Si no estuvieran allí, la consulta se vería normal y sería eficiente. Las consultas actualizadas de salida son perfectas y dinámicas.

¿Alguna idea?

¿Fue útil?

Solución

La pista podría estar en su elección de operación merge (). Del javadoc Hibernate:

  

Copia el estado del objeto dado   en el objeto persistente con el   mismo identificador Si no hay   instancia persistente actualmente   asociado con la sesión, lo hará   ser cargado.

Entonces, estás obligando a Hibernate a cargar todos los datos antes de modificarlos.

Pruebe una operación diferente, como update ():

  

Actualice la instancia persistente con   el identificador del dado separado   instancia.

Sin embargo, sin promesas, Hibernate podría decidir que necesita cargarlo de todos modos. La configuración dynamicUpdates = true podría empeorarla, ya que necesita saber qué hay para comenzar antes de poder emitir actualizaciones dinámicas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top