Hibernate 实体管理器 find() 仍然可以检索删除 hql 的实体

Posted

技术标签:

【中文标题】Hibernate 实体管理器 find() 仍然可以检索删除 hql 的实体【英文标题】:Hibernate entity manger find() still can retrieve the entities which delete hql 【发布时间】:2016-07-20 10:38:29 【问题描述】:

以下是我的代码:

    @Test
    public 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()));
    

本次测试失败,因为hql删除后,hibernate仍然可以找到被删除的实体。

日志:

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 - FmReportid=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970
18:25:36.277 [main] DEBUG o.h.internal.util.EntityPrinter - FmReportid=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970
18:25:36.277 [main] DEBUG o.h.internal.util.EntityPrinter - FmReportid=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 - FmReportid=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970
18:25:36.324 [main] DEBUG o.h.internal.util.EntityPrinter - FmReportid=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970
18:25:36.324 [main] DEBUG o.h.internal.util.EntityPrinter - FmReportid=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 - FmReportid=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970
18:25:36.338 [main] DEBUG o.h.internal.util.EntityPrinter - FmReportid=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970
18:25:36.338 [main] DEBUG o.h.internal.util.EntityPrinter - FmReportid=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 - FmReportid=3, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970
18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - FmReportid=2, alarmsJson=jsonString, date=Thu Jan 01 08:00:00 CST 1970
18:25:36.339 [main] DEBUG o.h.internal.util.EntityPrinter - FmReportid=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 connection

java.lang.AssertionError: expected null, but was:<FmReport@88dfd83>

同样的代码适用于 EclipseLink,但在 hibernate 中却没有。 我在问背后的原因是什么,或者休眠所需的具体配置是什么?

【问题讨论】:

【参考方案1】:

更正的是: entityManager.clear(); 应该在 sql 执行之前/之后运行。推荐的地方是之前。请查看When to Use EntityManager.clear()?

【讨论】:

以上是关于Hibernate 实体管理器 find() 仍然可以检索删除 hql 的实体的主要内容,如果未能解决你的问题,请参考以下文章

javax.persistence.PersistenceException:无法构建实体管理器工厂

使用实体管理器时,没有为该名称定义查询

当实体未更改时,Hibernate 在刷新期间保持实体

Seam3/Weld - 找不到实体管理器

ClassNotFound : 创建实体管理器工厂时的 javax.persistence.Persistence

Hibernate:覆盖实体获取器以添加注释