前段时间把项目中的JPA从EclipseLink换成Hibernate。这其中遇到了很多问题,也记录了一部分在其他的文章中。这里介绍一个UT中遇到的问题。
当时的测试是忘H2数据库中插入多项数据,然后用Query的方式删除,assert读出来的数据是null。这个测试用例在EclipseLink下面是可以通过的,但换成Hibernate之后发现数据仍然可以读出这个数据。
测试用例如下:

 @Testpublic void shouldRemovesAllFmReportFromDb(){FmReport fmReport1 = givenFmReportIsStoredInDb();FmReport fmReport2 = givenFmReportIsStoredInDb();FmReport fmReport3 = givenFmReportIsStoredInDb();Integer previousSize = getEntityManager().createQuery( "SELECT re FROM FmReport re" ).getResultList().size();System.out.println("*** before delete, the size is " + previousSize);FmReport fmReportById1 = getEntityManager().find(FmReport.class, fmReport1.getId());Assert.assertNotNull( fmReportById1 );getEntityManager().createQuery( "DELETE FROM FmReport" ).executeUpdate();Integer finalSize = getEntityManager().createQuery( "SELECT re FROM FmReport re" ).getResultList().size();System.out.println("*** after delete, the size is " + finalSize);Assert.assertNull( getEntityManager().find(FmReport.class, fmReport1.getId()));}

测试的log:

18:25:36.027 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
18:25:36.029 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
18:25:36.029 [main] DEBUG o.h.internal.SessionFactoryImpl - Checking 0 named SQL queries
18:25:36.042 [main] DEBUG o.h.s.internal.StatisticsInitiator - Statistics initialized [enabled=false]
18:25:36.105 [main] DEBUG o.h.e.i.EntityManagerFactoryRegistry - Initializing EntityManagerFactoryRegistry : org.hibernate.ejb.internal.EntityManagerFactoryRegistry@6ef93d8a
18:25:36.105 [main] DEBUG o.h.e.i.EntityManagerFactoryRegistry - Registering EntityManagerFactory: test-pu 18:25:36.216 [main] DEBUG o.h.e.t.spi.AbstractTransactionImpl - begin
18:25:36.216 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtaining JDBC connection
18:25:36.216 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtained JDBC connection
18:25:36.216 [main] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - initial autocommit status: true
18:25:36.216 [main] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - disabling autocommit
18:25:36.223 [main] DEBUG org.hibernate.SQL - select nextval ('fm_report_id_seq')
18:25:36.231 [main] DEBUG org.hibernate.id.SequenceGenerator - Sequence identifier generated: BasicHolder[java.lang.Long[1]]
18:25:36.234 [main] DEBUG o.h.e.i.AbstractSaveEventListener - Generated identifier: 1, using strategy: org.hibernate.id.SequenceHiLoGenerator
18:25:36.249 [main] DEBUG org.hibernate.SQL - select nextval ('fm_report_id_seq')
18:25:36.249 [main] DEBUG org.hibernate.id.SequenceGenerator - Sequence identifier generated: BasicHolder[java.lang.Long[2]]
18:25:36.249 [main] DEBUG o.h.e.i.AbstractSaveEventListener - Generated identifier: 2, using strategy: org.hibernate.id.SequenceHiLoGenerator
18:25:36.250 [main] DEBUG org.hibernate.SQL - select nextval ('fm_report_id_seq')
18:25:36.250 [main] DEBUG org.hibernate.id.SequenceGenerator - Sequence identifier generated: BasicHolder[java.lang.Long[3]]
18:25:36.250 [main] DEBUG o.h.e.i.AbstractSaveEventListener - Generated identifier: 3, using strategy: org.hibernate.id.SequenceHiLoGenerator
18:25:36.268 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Processing flush-time cascades
18:25:36.270 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collections
18:25:36.273 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 3 insertions, 0 updates, 0 deletions to 3 objects
18:25:36.273 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
18:25:36.274 [main] DEBUG o.h.internal.util.EntityPrinter - Listing entities:
18:25:36.277 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.277 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.277 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=1, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.277 [main] DEBUG org.hibernate.engine.spi.ActionQueue - Changes must be flushed to space: fm_report
18:25:36.289 [main] DEBUG org.hibernate.SQL - insert into fm_report (alarms_json, date, id) values (?, ?, ?)
18:25:36.295 [main] DEBUG org.hibernate.SQL - insert into fm_report (alarms_json, date, id) values (?, ?, ?)
18:25:36.296 [main] DEBUG org.hibernate.SQL - insert into fm_report (alarms_json, date, id) values (?, ?, ?)
18:25:36.300 [main] DEBUG org.hibernate.SQL - select fmreport0_.id as id1_0_, fmreport0_.alarms_json as alarms_j2_0_, fmreport0_.date as date3_0_ from fm_report fmreport0_
18:25:36.302 [main] DEBUG org.hibernate.loader.Loader - Result set row: 0
18:25:36.306 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[FmReport#1]
18:25:36.307 [main] DEBUG org.hibernate.loader.Loader - Result set row: 1
18:25:36.308 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[FmReport#2]
18:25:36.309 [main] DEBUG org.hibernate.loader.Loader - Result set row: 2
18:25:36.309 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[FmReport#3]
*** before delete, the size is 3
18:25:36.322 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Processing flush-time cascades
18:25:36.323 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collections
18:25:36.323 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 insertions, 0 updates, 0 deletions to 3 objects
18:25:36.324 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
18:25:36.324 [main] DEBUG o.h.internal.util.EntityPrinter - Listing entities:
18:25:36.324 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.324 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.324 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=1, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.330 [main] DEBUG org.hibernate.SQL - delete from fm_report
18:25:36.334 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Processing flush-time cascades
18:25:36.335 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collections
18:25:36.337 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 insertions, 0 updates, 0 deletions to 3 objects
18:25:36.337 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
18:25:36.337 [main] DEBUG o.h.internal.util.EntityPrinter - Listing entities:
18:25:36.337 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.338 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.338 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=1, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.338 [main] DEBUG org.hibernate.SQL - select fmreport0_.id as id1_0_, fmreport0_.alarms_json as alarms_j2_0_, fmreport0_.date as date3_0_ from fm_report fmreport0_
*** after delete, the size is 0
18:25:36.338 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Processing flush-time cascades
18:25:36.339 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collections
18:25:36.339 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 insertions, 0 updates, 0 deletions to 3 objects
18:25:36.339 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - Listing entities:
18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=1, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.339 [main] DEBUG o.h.e.t.spi.AbstractTransactionImpl - rolling back
18:25:36.343 [main] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - rolled JDBC Connection
18:25:36.343 [main] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - re-enabling autocommit
18:25:36.346 [main] DEBUG o.h.e.j.internal.JdbcCoordinatorImpl - HHH000420: Closing un-released batch
18:25:36.346 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Releasing JDBC connection
18:25:36.346 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Released JDBC connectionjava.lang.AssertionError: expected null, but was:<FmReport@88dfd83>

可以在Log中明显看到执行了对应的删除的sql语句:
18:25:36.330 [main] DEBUG org.hibernate.SQL - delete from fm_report
并且再用select语句读取数据库时,数据是真实从数据库中删掉了的,但为什么entityManager的find()函数还是能够读取到对应的entity呢?
并且entity printer的打印显示它们仍然存在:

18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - Listing entities:
18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - FmReport{id=1, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}

分析得出的结论是:

  • hibernate query的executeUpdate()是直接对数据库进行操作
  • executeUpdate()不对cache进行更新,executeUpdate()会造成find()和query select的不同步。

这点在JBoss的官网上有描述:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html#batch-direct

This means that manipulating data directly in the database (using the SQL Data Manipulation Language (DML) the statements: INSERT, UPDATE, DELETE) will not affect in-memory state. However, Hibernate provides methods for bulk SQL-style DML statement execution that is performed through the Hibernate Query Language (HQL).

并且,hibernate做了多次的dirty checking collections:

    Line 21: 18:25:36.270 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collectionsLine 41: 18:25:36.323 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collectionsLine 50: 18:25:36.335 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collectionsLine 60: 18:25:36.339 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collections

可见,除了出现在hibernate中使用query是有比较大的performance的开销。
但注意,这个问题不是common的,不同的JPA有不同的实现方式,EclipseLink就没有这个问题。
那我们该怎么解决呢?
问题的关键在于同步cache/mem中的数据与数据库同步,调用clear()函数可以解决这个问题:

        getEntityManager().clear();getEntityManager().createQuery( "delete FmReport" ).executeUpdate();

Log:

14:14:16.348 [main] DEBUG o.h.h.i.ast.QueryTranslatorImpl - --- HQL AST ---\-[DELETE] Node: 'DELETE'\-[FROM] Node: 'FROM'\-[RANGE] Node: 'RANGE'\-[DOT] Node: '.'+-[DOT] Node: '.'|  +-[DOT] Node: '.'|  |  +-[DOT] Node: '.'|  |  |  +-[DOT] Node: '.'|  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  |  |  |  |  +-[IDENT] Node: 'com'|  |  |  |  |  |  |  |  |  \-[IDENT] Node: 'nsn'|  |  |  |  |  |  |  |  \-[IDENT] Node: 'ood'|  |  |  |  |  |  |  \-[IDENT] Node: 'cp'|  |  |  |  |  |  \-[IDENT] Node: 'aswu'|  |  |  |  |  \-[IDENT] Node: 'fm'|  |  |  |  \-[IDENT] Node: 'nms'|  |  |  \-[IDENT] Node: 'db'|  |  \-[IDENT] Node: 'report'|  \-[IDENT] Node: 'domain'\-[IDENT] Node: 'FmReport'14:14:16.348 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
14:14:16.352 [main] DEBUG o.h.h.i.antlr.HqlSqlBaseWalker - delete << begin [level=1, statement=delete]
14:14:16.353 [main] DEBUG o.h.h.internal.ast.tree.FromElement - FromClause{level=1} : com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport (<no alias>) -> fmreport0_
14:14:16.354 [main] DEBUG o.h.h.i.antlr.HqlSqlBaseWalker - delete : finishing up [level=1, statement=delete]
14:14:16.354 [main] DEBUG o.h.h.i.antlr.HqlSqlBaseWalker - delete >> end [level=1, statement=delete]
14:14:16.355 [main] DEBUG o.h.h.i.ast.QueryTranslatorImpl - --- SQL AST ---\-[DELETE] DeleteStatement: 'DELETE'  querySpaces (fm_report)\-[FROM] FromClause: 'FROM' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[], fromElementByTableAlias=[fmreport0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]}\-[FROM_FRAGMENT] FromElement: 'fm_report' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=fm_report,tableAlias=fmreport0_,origin=null,columns={,className=com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport}}14:14:16.355 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
14:14:16.358 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
14:14:16.358 [main] DEBUG o.h.internal.SessionFactoryImpl - Checking 0 named SQL queries
14:14:16.369 [main] DEBUG o.h.s.internal.StatisticsInitiator - Statistics initialized [enabled=false]
14:14:16.449 [main] DEBUG o.h.e.i.EntityManagerFactoryRegistry - Initializing EntityManagerFactoryRegistry : org.hibernate.ejb.internal.EntityManagerFactoryRegistry@775dfcbc
14:14:16.449 [main] DEBUG o.h.e.i.EntityManagerFactoryRegistry - Registering EntityManagerFactory: test-pu 14:14:16.589 [main] DEBUG o.h.e.t.spi.AbstractTransactionImpl - begin
14:14:16.589 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtaining JDBC connection
14:14:16.589 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtained JDBC connection
14:14:16.589 [main] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - initial autocommit status: true
14:14:16.589 [main] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - disabling autocommit
14:14:16.597 [main] DEBUG org.hibernate.SQL - select nextval ('fm_report_id_seq')
14:14:16.619 [main] DEBUG org.hibernate.id.SequenceGenerator - Sequence identifier generated: BasicHolder[java.lang.Long[1]]
14:14:16.624 [main] DEBUG o.h.e.i.AbstractSaveEventListener - Generated identifier: 1, using strategy: org.hibernate.id.SequenceHiLoGenerator
14:14:16.644 [main] DEBUG org.hibernate.SQL - select nextval ('fm_report_id_seq')
14:14:16.645 [main] DEBUG org.hibernate.id.SequenceGenerator - Sequence identifier generated: BasicHolder[java.lang.Long[2]]
14:14:16.645 [main] DEBUG o.h.e.i.AbstractSaveEventListener - Generated identifier: 2, using strategy: org.hibernate.id.SequenceHiLoGenerator
14:14:16.645 [main] DEBUG org.hibernate.SQL - select nextval ('fm_report_id_seq')
14:14:16.645 [main] DEBUG org.hibernate.id.SequenceGenerator - Sequence identifier generated: BasicHolder[java.lang.Long[3]]
14:14:16.645 [main] DEBUG o.h.e.i.AbstractSaveEventListener - Generated identifier: 3, using strategy: org.hibernate.id.SequenceHiLoGenerator
14:14:16.665 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Processing flush-time cascades
14:14:16.666 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collections
14:14:16.669 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 3 insertions, 0 updates, 0 deletions to 3 objects
14:14:16.669 [main] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
14:14:16.672 [main] DEBUG o.h.internal.util.EntityPrinter - Listing entities:
14:14:16.675 [main] DEBUG o.h.internal.util.EntityPrinter - com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport{id=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
14:14:16.675 [main] DEBUG o.h.internal.util.EntityPrinter - com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport{id=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
14:14:16.676 [main] DEBUG o.h.internal.util.EntityPrinter - com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport{id=1, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970}
14:14:16.676 [main] DEBUG org.hibernate.engine.spi.ActionQueue - Changes must be flushed to space: fm_report
14:14:16.693 [main] DEBUG org.hibernate.SQL - insert into fm_report (alarms_json, date, id) values (?, ?, ?)
14:14:16.702 [main] DEBUG org.hibernate.SQL - insert into fm_report (alarms_json, date, id) values (?, ?, ?)
14:14:16.703 [main] DEBUG org.hibernate.SQL - insert into fm_report (alarms_json, date, id) values (?, ?, ?)
14:14:16.711 [main] DEBUG org.hibernate.SQL - select fmreport0_.id as id1_0_, fmreport0_.alarms_json as alarms_j2_0_, fmreport0_.date as date3_0_ from fm_report fmreport0_
14:14:16.712 [main] DEBUG org.hibernate.loader.Loader - Result set row: 0
14:14:16.715 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport#1]
14:14:16.715 [main] DEBUG org.hibernate.loader.Loader - Result set row: 1
14:14:16.715 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport#2]
14:14:16.715 [main] DEBUG org.hibernate.loader.Loader - Result set row: 2
14:14:16.715 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport#3]
*** before delete, the size is 3
14:14:16.723 [main] DEBUG o.h.h.i.ast.QueryTranslatorImpl - parse() - HQL: delete com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport
14:14:16.726 [main] DEBUG o.h.h.i.ast.QueryTranslatorImpl - --- HQL AST ---\-[DELETE] Node: 'delete'\-[FROM] Node: 'FROM'\-[RANGE] Node: 'RANGE'\-[DOT] Node: '.'+-[DOT] Node: '.'|  +-[DOT] Node: '.'|  |  +-[DOT] Node: '.'|  |  |  +-[DOT] Node: '.'|  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  |  |  |  +-[DOT] Node: '.'|  |  |  |  |  |  |  |  |  +-[IDENT] Node: 'com'|  |  |  |  |  |  |  |  |  \-[IDENT] Node: 'nsn'|  |  |  |  |  |  |  |  \-[IDENT] Node: 'ood'|  |  |  |  |  |  |  \-[IDENT] Node: 'cp'|  |  |  |  |  |  \-[IDENT] Node: 'aswu'|  |  |  |  |  \-[IDENT] Node: 'fm'|  |  |  |  \-[IDENT] Node: 'nms'|  |  |  \-[IDENT] Node: 'db'|  |  \-[IDENT] Node: 'report'|  \-[IDENT] Node: 'domain'\-[IDENT] Node: 'FmReport'14:14:16.726 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
14:14:16.727 [main] DEBUG o.h.h.i.antlr.HqlSqlBaseWalker - delete << begin [level=1, statement=delete]
14:14:16.727 [main] DEBUG o.h.h.internal.ast.tree.FromElement - FromClause{level=1} : com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport (<no alias>) -> fmreport0_
14:14:16.727 [main] DEBUG o.h.h.i.antlr.HqlSqlBaseWalker - delete : finishing up [level=1, statement=delete]
14:14:16.727 [main] DEBUG o.h.h.i.antlr.HqlSqlBaseWalker - delete >> end [level=1, statement=delete]
14:14:16.728 [main] DEBUG o.h.h.i.ast.QueryTranslatorImpl - --- SQL AST ---\-[DELETE] DeleteStatement: 'delete'  querySpaces (fm_report)\-[FROM] FromClause: 'FROM' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[], fromElementByTableAlias=[fmreport0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]}\-[FROM_FRAGMENT] FromElement: 'fm_report' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=fm_report,tableAlias=fmreport0_,origin=null,columns={,className=com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport}}14:14:16.728 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
14:14:16.728 [main] DEBUG o.h.hql.internal.ast.ErrorCounter - throwQueryException() : no errors
14:14:16.730 [main] DEBUG org.hibernate.SQL - delete from fm_report
14:14:16.732 [main] DEBUG org.hibernate.SQL - select fmreport0_.id as id1_0_, fmreport0_.alarms_json as alarms_j2_0_, fmreport0_.date as date3_0_ from fm_report fmreport0_
*** after delete, the size is 0
14:14:16.733 [main] DEBUG org.hibernate.loader.Loader - Loading entity: [com.nsn.ood.cp.aswu.fm.nms.db.report.domain.FmReport#1]
14:14:16.733 [main] DEBUG org.hibernate.SQL - select fmreport0_.id as id1_0_0_, fmreport0_.alarms_json as alarms_j2_0_0_, fmreport0_.date as date3_0_0_ from fm_report fmreport0_ where fmreport0_.id=?
14:14:16.733 [main] DEBUG org.hibernate.loader.Loader - Done entity load
14:14:16.734 [main] DEBUG o.h.e.t.spi.AbstractTransactionImpl - rolling back
14:14:16.738 [main] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - rolled JDBC Connection
14:14:16.738 [main] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - re-enabling autocommit
14:14:16.739 [main] DEBUG o.h.e.j.internal.JdbcCoordinatorImpl - HHH000420: Closing un-released batch
14:14:16.739 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Releasing JDBC connection
14:14:16.739 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Released JDBC connection

这下清爽了许多,而且也没有了dirty checking的开销

但需要注意的是:

    /*** Clear the persistence context, causing all managed* entities to become detached. Changes made to entities that* have not been flushed to the database will not be* persisted.*/public void clear();

如果在clear之前我们有还有没提交的transaction, 那之前保存在内存中还没提交到数据库的修改就会被丢弃。
因此,所有的saveOrUpdate操作必须有事务控制。
另外,关于何时调用clear()函数是有比较好的总结的:

Clearing the entity manager empties its associated cache, forcing new database queries to be executed later in the transaction. It’s almost never necessary to clear the entity manager when using a transaction-bound entity manager. I see two reasons to clear:

  • when doing batch processing, in order to avoid having a giant cache eating memory and increasing the time to flush because of long dirty checks
  • when you’re doing DML or SQL queries, which completely bypass the entity manager cache. In this case, the state held by the cache doesn’t reflect what is in the database because of the queries, so you want to clear the cache to avoid this inconsistency.

Hibernate用Query删除数据表中的数据的问题(EntityManager.clear())相关推荐

  1. php怎么删除表数据,php怎样删除数据表中的数据_后端开发

    php删除数据表中的数据的要领:能够经由过程mysqli_query()函数连系DELETE FROM语句来举行删除.DELETE FROM语句用于从数据库表中删除纪录,语法结构为:[DELETE F ...

  2. oracle的删除的row如何,Oracle 删除大表中部分数据

    需求: 项目中有一张表大概有7000多万条数据,造成表空间已满,需要清理部分数据,打算清理3000万. 2B 做法: delete from table_name where ID > '400 ...

  3. mysql中清空数据表中的数据,不删除数据表

    1.清空不带外键约束的数据表中的数据 使用delete语句清空`t_test`表中的数据 delete from `t_test`; 使用truncate语句清空`t_test`表中的数据 trunc ...

  4. MySQL - 删除数据库表中的数据

    删除数据库表中的数据 删除数据记录是数据操作中常见的操作,可以删除表中已经存在的数据记录.在MySQL中可以通过DELETE语句来删除数据记录,该SQL语句可以通过以下几种方式使用:删除特定数据记录. ...

  5. oracle 两表去除重复的数据,Oracle数据库删除两表中相同数据的方法

    在Oracle数据库中删除两表中相同数据的方法是用到in语句,本文通过实例来讲解删除两表中相同数据的方法. 软件环境: 1.Windows NT4.0+ORACLE 8.0.4. 2.Oracle安装 ...

  6. 数据库笔记03:管理数据表中的数据

    /***************************  第三单元:管理数据表中的数据 ***************************/ /************************* ...

  7. xlsx表格怎么做汇总统计_Excel表格中如何快速汇总多个数据表中的数据

    原标题:Excel表格中如何快速汇总多个数据表中的数据 在Excel工作表中,如果需要汇总报告多个单独单元格的结果,可以将这些单元格中的数据合并到一个主工作表中.这些工作表可以与主工作表在同一个工作簿 ...

  8. 17.2.3 通过查看triggers数据表中的数据查看触发器的信息

    17.2.3 通过查看triggers数据表中的数据查看触发器的信息 在MySQL中,会将触发器的信息存储到information_schema数据库中的triggers数据表中.可以通过查看info ...

  9. 编写Scala代码,使用Spark讲Mysql数据表中的数据抽取到Hive的ODS层

    编写Scala代码,使用Spark讲Mysql数据表中的数据抽取到Hive的ODS层 抽取MySQL的metast库中Production表的全量数据进入Hive的ods库中表production,字 ...

  10. mysql视图中可以删除数据吗_sql問題 删除视图中的数据,表中的数据会删除吗?

    如果你那个视图,是 单表的, 没写 触发器的. 那么 如果 删除视图中的数据 成功了,那么 表中的数据 就被删除了. 如果那个视图, 写了个 INSTEAD OF 触发器. 但是里面没有任何删除的动作 ...

最新文章

  1. 互联网人的生存指南 | 每日趣闻
  2. 一篇小的随笔,关于记忆算法和概念
  3. 内核编程小结(引用)
  4. 个推开发者服务进阶之路
  5. centos配置mysql
  6. jquery设置表单元素只读_jquery设置元素readonly和disabled(checkbox只读)
  7. su如何变成实体_紫天学习星球教学:如何在SU里把JPG图片变成三维模型
  8. C语言学习笔记(五):《C语言深度剖析》笔记
  9. 置换贴图,法线贴图和凹凸贴图详解
  10. Merged region B8 must contain 2 or more cells
  11. js修改div标签中的内容
  12. 消防基础知识——燃烧与火灾
  13. 让假照片原形毕露?今日水印相机上线“照片验真”功能
  14. Accuracy and precision 意义
  15. python模块相互引用_python导入模块交叉引用的方法
  16. 软件设计模式——建造者模式
  17. windows11下vone客户端无法启动问题
  18. C语言年历显示主菜单怎么做,c语言程序的设计年历显示.doc
  19. Windows Media Player on Firefox
  20. short、int、long、long long

热门文章

  1. (8)安装适合cuda10.0的显卡驱动(显卡940M升级驱动)
  2. java谜题读书笔记_《java深度历险》读书笔记(一)
  3. VuePress开启评论、VuePress评论功能。
  4. 【基于IPD的产品开发体系】推行实践
  5. oracle查看job运行,oracle job使用详解及job不运行的检查方法
  6. 集团申请选择企业邮箱注意事项
  7. 空间后方交会编程c语言,C语言空间后方交会源代码.doc
  8. I2C通讯常见问题汇总
  9. 如何用html来编写ppt,impress.js——用HTML“写”幻灯片
  10. Flask 物联网局部应用情景