Fare in modo che Hibernate esegua semplici aggiornamenti, invece di selezionare enormemente quindi gli aggiornamenti

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

Domanda

Consente di impostare prima la domanda.

Quello che ho sono > 4 tabelle: cliente, indirizzo, ordine, oggetti ordine. Ciascuno è mappato utilizzando Annotazioni ibernazione e vi si accede tramite un livello DAO / Servizi Spring.

Quello che sto cercando di fare è unire i clienti duplicati. Quindi tutto ciò che deve realmente accadere sono tutti gli ordini e gli indirizzi associati al cliente B, è necessario aggiornare la chiave esterna customer_id per puntare al cliente A. Quindi il cliente B deve avere il bit disabilitato impostato.

Invece di inviare queste semplici query al nostro database, l'ibernazione impazzisce e genera moltissime query di selezione e aggiornamento. In particolare seleziona tutti gli articoli dell'ordine collegati a un ordine (perché questo è definito EAGER e questo punto non è modificabile.). Per ottenere le selezioni prima dell'aggiornamento per smettere di succedere, ho provato ad aggiungere l'annotazione dell'entità ibernazione in cima al normale javax.persistence.Entity come:

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

questo sembra non avere alcun effetto, tranne che con semplici query in cui ha aggiornato solo singoli elementi in una tabella.

Ottengo gli oggetti usando i seguenti criteri di ibernazione:

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

Quindi sposto tutti gli indirizzi e ordino gli oggetti dal cliente B al cliente A ed eseguo un

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

su entrambi gli oggetti cliente. Questo finisce per creare un sacco di istruzioni selezionate che ottengono tutti gli oggetti associati (ad esempio OrderItems, Products, ProductType, ProductPricingTmpl, ecc.)

Devo rimuovere queste selezioni! Se non ci fossero, la query sembrerebbe normale ed efficiente! Le query di aggiornamento generate sono perfette e dinamiche.

Qualche idea?

È stato utile?

Soluzione

L'indizio potrebbe essere nella scelta dell'operazione merge (). Da Hibernate javadoc:

  

Copia lo stato dell'oggetto indicato   sull'oggetto persistente con il   stesso identificatore. Se non c'è   istanza persistente attualmente   associato alla sessione, lo farà   essere caricato.

Quindi stai forzando Hibernate a caricare tutti i dati prima di modificarli.

Prova un'operazione diversa, come update ():

  

Aggiorna l'istanza persistente con   l'identificatore del dato distaccato   esempio.

Nessuna promessa, tuttavia, Hibernate potrebbe decidere di caricarlo comunque. DynamicUpdates = true config potrebbe effettivamente peggiorare le cose, poiché deve sapere cosa c'è prima di poter emettere aggiornamenti dinamici.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top