Самый быстрый способ удаления нескольких объектов в Hibernate - PullRequest
14 голосов
/ 30 марта 2012

Я использую Hibernate для удаления объекта, который имеет два каскадных уровня, и моя проблема в том, что он ОЧЕНЬ медленный, когда я запрашиваю объекты, а затем удаляю, и мне интересно узнать, есть ли более быстрый способ. Мой код, который занимает около 15-30 секунд, чтобы удалить 15 Statement объектов выглядит так:

public void deleteStatement(Long batchId) {
    List<Statement> statements = session.createQuery("from Statement where batchId = ?").setParameter(0, batchId).list();
    for(Statement statement : statements) {
        session.delete(statement);
        logger.debug("Deleted statement");
    }
}

Я знаю, что мог бы просто сделать:

session.createQuery("delete from Statement where batchId = ?").setParameter(0, batchId).executeUpdate();

но проблема в том, что каскады удаления не происходят с этим методом. Есть ли эффективный способ удалить мои объекты и при этом иметь место каскад, или я что-то не так делаю?

Спасибо за помощь!

Обновление
В ответ на davidfrancis, вот парафраз SQL, который генерирует hibernate. Это безумие и тысячи строк, верьте этому или нет !! Обратите внимание, мой объект домена, Statement, содержит набор Invoice, который содержит набор Transaction. Я лениво загружаю все свои коллекции, кстати. Во-первых, есть большой выбор данных, который, я думаю, происходит с запросом выбора HQL:

org.hibernate.hql.ast.QueryTranslatorImpl - HQL: from com.myapp.domain.cc.Statement where batchId = ?
org.hibernate.hql.ast.QueryTranslatorImpl - SQL: select statement0_.id as id2_, statement0_.batchId as batchId2_ from statement statement0_ where batchId=?
org.hibernate.loader.Loader - result row: EntityKey[com.myapp.domain.cc.Statement#393]
org.hibernate.loader.Loader - result row: EntityKey[com.myapp.domain.cc.Statement#394]
...
org.hibernate.SQL - select invoices0_.statementId as stateme12_2_1_, invoices0_.id as id1_, invoices0_.id as id3_0_,  invoices0_.statementId as stateme12_3_0_ from invoice invoices0_ where invoices0_.statementId=?
org.hibernate.loader.Loader - result row: EntityKey[com.myapp.domain.cc.Invoice#48987]
org.hibernate.loader.Loader - found row of collection: [com.myapp.domain.cc.Statement.invoices#393]
org.hibernate.loader.Loader - result row: EntityKey[com.myapp.domain.cc.Invoice#48988]
org.hibernate.loader.Loader - found row of collection: [com.myapp.domain.cc.Statement.invoices#393]
...
org.hibernate.SQL - select transactio0_.invoiceId as invoiceId3_1_, transactio0_.id as id1_, transactio0_.id as id4_0_,  transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ where transactio0_.invoiceId=?
org.hibernate.loader.Loader - result row: EntityKey[com.myapp.domain.cc.Transaction#306534]
org.hibernate.loader.Loader - found row of collection: [com.myapp.domain.cc.Invoice.transactions#48996]
...

Теперь удаление:

org.hibernate.persister.entity.AbstractEntityPersister - Static SQL for entity: com.aa.itfs.mcla.domain.cc.Transaction
org.hibernate.persister.entity.AbstractEntityPersister -  Version select: select id from transactions where id =?
org.hibernate.persister.entity.AbstractEntityPersister -  Snapshot select: select transactio_.id, transactio_.ccNumber as ccNumber4_, transactio_.approvalCode as approval3_4_, transactio_.saleAmount as saleAmount4_, transactio_.installmentNumber as installm5_4_, transactio_.numberOfInstallments as numberOf6_4_ from transactions transactio_ where transactio_.id=?
org.hibernate.persister.entity.AbstractEntityPersister -  Insert 0: insert into transactions (ccNumber, approvalCode, saleAmount, installmentNumber, numberOfInstallments, invoiceId, id) values (?, ?, ?, ?, ?, ?, ?)
org.hibernate.persister.entity.AbstractEntityPersister -  Update 0: update transactions set ccNumber=?, approvalCode=?, saleAmount=?, installmentNumber=?, numberOfInstallments=? where id=?
org.hibernate.persister.entity.AbstractEntityPersister -  Delete 0: delete from transactions where id=?
org.hibernate.persister.entity.AbstractEntityPersister -  Identity insert: insert into transactions (ccNumber, approvalCode, saleAmount, installmentNumber, numberOfInstallments, invoiceId) values (?, ?, ?, ?, ?, ?)
org.hibernate.persister.entity.AbstractEntityPersister - Static SQL for entity: com.myapp.domain.cc.Statement
org.hibernate.persister.entity.AbstractEntityPersister -  Version select: select id from statement where id =?
org.hibernate.persister.entity.AbstractEntityPersister -  Snapshot select: select statement_.id, statement_.statementNumber as statemen2_2_, statement_.filename as filename2_, statement_.statementType as statemen4_2_ from statement statement_ where statement_.id=?
org.hibernate.persister.entity.AbstractEntityPersister -  Insert 0: insert into statement (statementNumber, filename, statementType, batchId, id) values (?, ?, ?, ?, ?)
org.hibernate.persister.entity.AbstractEntityPersister -  Update 0: update statement set statementNumber=?, filename=?, statementType=? where id=?
org.hibernate.persister.entity.AbstractEntityPersister -  Delete 0: delete from statement where id=?
org.hibernate.persister.entity.AbstractEntityPersister -  Identity insert: insert into statement (statementNumber, filename, statementType, batchId) values (?, ?, ?, ?)
org.hibernate.persister.collection.AbstractCollectionPersister - Static SQL for collection: com.myapp.domain.cc.Statement.invoices
org.hibernate.persister.collection.AbstractCollectionPersister -  Row insert: update invoice set statementId=? where id=?
org.hibernate.persister.collection.AbstractCollectionPersister -  Row delete: update invoice set statementId=null where statementId=? and id=?
org.hibernate.persister.collection.AbstractCollectionPersister -  One-shot delete: update invoice set statementId=null where statementId=?
org.hibernate.persister.collection.AbstractCollectionPersister - Static SQL for collection: com.myapp.domain.cc.Invoice.transactions
org.hibernate.persister.collection.AbstractCollectionPersister -  Row insert: update transactions set invoiceId=? where id=?
org.hibernate.persister.collection.AbstractCollectionPersister -  Row delete: update transactions set invoiceId=null where invoiceId=? and id=?
org.hibernate.persister.collection.AbstractCollectionPersister -  One-shot delete: update transactions set invoiceId=null where invoiceId=?    

Случайный выбор ....

org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [NONE]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [READ]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [UPGRADE]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ with (updlock, rowlock) where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [UPGRADE_NOWAIT]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ with (updlock, rowlock) where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [FORCE]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [PESSIMISTIC_READ]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ with (holdlock, rowlock) where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [PESSIMISTIC_WRITE]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ with (updlock, rowlock) where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [PESSIMISTIC_FORCE_INCREMENT]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [OPTIMISTIC]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Invoice [OPTIMISTIC_FORCE_INCREMENT]: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for action ACTION_MERGE on entity com.myapp.domain.cc.Invoice: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for action ACTION_REFRESH on entity com.myapp.domain.cc.Invoice: select invoice0_.id as id3_0_, invoice0_.invoiceNumber as invoiceN2_3_0_, invoice0_.merchantNumber as merchant3_3_0_, invoice0_.installmentNumber as installm4_3_0_, invoice0_.saleDate as saleDate3_0_, invoice0_.paymentDate as paymentD6_3_0_, invoice0_.amount as amount3_0_, invoice0_.amountType as amountType3_0_, invoice0_.saleType as saleType3_0_, invoice0_.ccType as ccType3_0_, invoice0_.statementType as stateme11_3_0_, invoice0_.statementId as stateme12_3_0_ from invoice invoice0_ where invoice0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [NONE]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [READ]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [UPGRADE]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ with (updlock, rowlock) where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [UPGRADE_NOWAIT]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ with (updlock, rowlock) where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [FORCE]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [PESSIMISTIC_READ]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ with (holdlock, rowlock) where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [PESSIMISTIC_WRITE]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ with (updlock, rowlock) where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [PESSIMISTIC_FORCE_INCREMENT]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [OPTIMISTIC]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for entity com.myapp.domain.cc.Transaction [OPTIMISTIC_FORCE_INCREMENT]: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for action ACTION_MERGE on entity com.myapp.domain.cc.Transaction: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ where transactio0_.id=?
org.hibernate.loader.entity.EntityLoader - Static select for action ACTION_REFRESH on entity com.myapp.domain.cc.Transaction: select transactio0_.id as id4_0_, transactio0_.ccNumber as ccNumber4_0_, transactio0_.approvalCode as approval3_4_0_, transactio0_.saleAmount as saleAmount4_0_, transactio0_.installmentNumber as installm5_4_0_, transactio0_.numberOfInstallments as numberOf6_4_0_, transactio0_.invoiceId as invoiceId4_0_ from transactions transactio0_ where transactio0_.id=?
...

Извините за беспорядок! Спросите, и вы получите:)

1 Ответ

7 голосов
/ 30 марта 2012

Самый быстрый способ - удалить вручную.Вам придется использовать отдельные операторы delete для каждого из дочерних элементов, а не полагаться на каскад.Вам также необходимо сначала удалить дочерние элементы, чтобы избежать временного нарушения отношений с внешним ключом.

В качестве альтернативы вы можете ускорить его, используя прокси-выборку.Вероятно, большую часть времени тратится на выборку ненужных данных.Когда вы используете прокси-выборку, Hibernate будет только выбирать идентификаторы и создавать прокси-объекты, которые будут создавать себя при первом использовании.Однако, поскольку вы немедленно удаляете их, их не нужно создавать.

...