Spring JPA/Hibernate org.hibernate.AssertionFailure: null id in Entity (don't flush the Session after an exception occurs)

Priya

Experts/Gurus/Friends

Our application runs with Spring 3.2, JPA 2, Hibernate 4.2 tech stack with MySQL & Tomcat 7. We are getting a weird exception which is quite a puzzle to solve. We have a very simple entity which works well through Junit test without any issues. But when I added Hibernate EmptyInterceptor (moved the common company logic in here) then I get the below mentioned exception.. Alternatively I even tried with Hibernate PreInsertEventListener also but same exception.

After reading few posts in stackoverflow - this and this and few others, it makes me to think that read operation using EntityManager (in Interceptor) is triggering auto flush which causes exception to be thrown. But couldn't identify what it is. Also I have remove any not null constrains in this simple Entity class as well as in table (which dont even have a foreign key).

MYSQL Table

    CREATE TABLE  `rcent_rel_2`.`worklist_status_master` (
              `worklist_status_seqid` int(10) unsigned NOT NULL AUTO_INCREMENT,
              `worklist_status_name` varchar(45) DEFAULT NULL,
              `created_by` varchar(45) DEFAULT '',
              `updated_ts` datetime DEFAULT NULL,
              `updated_by` varchar(45) DEFAULT '',
              `comp_seq_id` int(10) unsigned DEFAULT NULL,
              `created_ts` datetime DEFAULT NULL,
              PRIMARY KEY (`worklist_status_seqid`)
            ) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=latin1;

Simple Entity

@Entity
@Table(name="worklist_status_master")
public class WorklistStatusDO  implements Serializable {
    private static final long serialVersionUID = 1L; 
    private static final Logger log = LoggerFactory.getLogger(WorklistStatusDO.class);

    private Integer id;
    private String workListStatusName;

    @Id
    //@GeneratedValue(strategy = GenerationType.IDENTITY) -- Tried this too
    @GeneratedValue
    @Column(name="worklist_status_seqid")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name="worklist_status_name")
    public String getWorkListStatusName() {
        return workListStatusName;
    }
    public void setWorkListStatusName(String workListStatusName) {
        this.workListStatusName = workListStatusName;
    }
    public WorklistStatusDO workListStatusName(String workListStatusName) {
        setWorkListStatusName(workListStatusName);
        return this;
    }

    @Override
    public String toString(){
        return Objects.toStringHelper(this).
                add("workListStatusName", getWorkListStatusName()).toString();
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }
    @Override
    public boolean equals(Object obj) {
        return (this == obj || (obj instanceof WorklistStatusDO && obj.hashCode() == hashCode()));
    }
}

Junit working scenairo

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value =  "classpath*:/spring/applicationContext.xml")
@Transactional
public class WorklistStatusTest {

    @PersistenceContext
    private EntityManager entityManager;

    @Test
    public void saveWorklistStatus(){
        CompanyInfo.setCompanyName("ABC");
        UserInfo.setUserId("XYZ");

        WorklistStatusDO worklistStatus = new WorklistStatusDO();
        worklistStatus.workListStatusName("test");

        // Company Logic
        javax.persistence.Query query = entityManager.createQuery("Select c From CompanyMasterDO c Where c.companyName =:companyName");
        query.setParameter("companyName", CompanyInfo.getCompanyName());
        CompanyMasterDO companyMasterDO = (CompanyMasterDO) query.getSingleResult();

        assertThat(companyMasterDO).isNotNull();

        entityManager.persist(worklistStatus);
    }

}

Junit failing scenario due to below Exception after moving Company Logic out to Interceptor

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value =  "classpath*:/spring/applicationContext.xml")
@Transactional
public class WorklistStatusTest {

    @PersistenceContext
    private EntityManager entityManager;

    @Test
    public void saveWorklistStatus(){
        CompanyInfo.setCompanyName("ABC");
        UserInfo.setUserId("XYZ");

        WorklistStatusDO worklistStatus = new WorklistStatusDO();
        worklistStatus.workListStatusName("test");

        // Company Logic moved to Interceptor

        entityManager.persist(worklistStatus);
    }

}

EmptyInterceptor

@Named
@Transactional
public class AuditEmptyInterceptor extends EmptyInterceptor {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public boolean onSave(Object entity, Serializable id, Object[] currentState,
            String[] propertyNames, Type[] types) {

        System.out.println("*********************inside OnSave() in Audit Empty Interceptor******************");
        javax.persistence.Query query = entityManager.createQuery("Select c From CompanyMasterDO c Where c.companyName =:companyName");
        query.setParameter("companyName", CompanyInfo.getCompanyName());
        CompanyMasterDO companyMasterDO = (CompanyMasterDO) query.getSingleResult();

        return false;
    }

Exception

    org.hibernate.AssertionFailure: null id in com.work.WorklistStatusDO entry (don't flush the Session after an exception occurs)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:79)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:194)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:156)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:228)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:100)
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1205)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1262)
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
    at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:287)
    at com.company.demo.audit.AuditEmptyInterceptor.onSave(AuditEmptyInterceptor.java:45)
    at com.company.demo.audit.StaticDelegateInterceptor.onSave(StaticDelegateInterceptor.java:24)
    at org.hibernate.event.internal.AbstractSaveEventListener.substituteValuesIfNecessary(AbstractSaveEventListener.java:387)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:268)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78)
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:853)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:827)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:831)
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:875)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
    at com.sun.proxy.$Proxy49.persist(Unknown Source)
    at com.rcent.test.worklist.WorklistStatusTest.saveWorklistStatus(WorklistStatusTest.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Note:

Had an issue earlier with injecting EmptyInterceptor. This is now solved here in stackoverflow. Thanks to Ricardo.

Ricardo Veguilla

Try using a Hibernate EventListener instead of Interceptors:

@Component
public class AuditEventListener implements PersistEventListener, DeleteEventListener, MergeEventListener, PreInsertEventListener {

  @PersistenceContext
  private EntityManager entityManager;

     @Override 
     public boolean onPreInsert(PreInsertEvent event) {
          return false; 
     } 

     @Override
     public void onPersist(PersistEvent event) {
        // you business logic
     }

     ... 
     ...
}

You can register the listener using this bean:

@Component
public class HibernateListenerRegistrar {
   @PersistenceUnit
   private EntityManagerFactory entityManagerFactory;

   @Autowired
   private AuditEventListener auditEventListener;

   @PostConstruct
   public void registerListeners() {
      if(entityManagerFactory instanceof HibernateEntityManagerFactory) {
          final HibernateEntityManagerFactory  hibernateEntityManagerFactory = (HibernateEntityManagerFactory) entityManagerFactory;
          final SessionFactoryImpl sessionFactory =  (SessionFactoryImpl) hibernateEntityManagerFactory.getSessionFactory();
          final EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
          registry.getEventListenerGroup(EventType.PERSIST).appendListener(auditEventListener);
          registry.getEventListenerGroup(EventType.MERGE).appendListener(auditEventListener);
          registry.getEventListenerGroup(EventType.DELETE).appendListener(auditEventListener);
          registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(auditEventListener);
          // register other events here
      }
    }
}

Edit

This approach won't work if you want to perform queries during the PRE_INSERT event and your IDs are generated by the database. If you manually generate Ids (or fetch them from the database before the transaction), you should be able to perform queries on during PRE_INSERT without problem. I've tested this using manually assigned IDs.

Depending on what your audit requirement is, you probably could implement the logic during the PERSIST event (which occurs after Hibernate has generated the IDs).

Hope this helps.

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Spring JPA / Hibernate org.hibernate.AssertionFailure:实体中的id为null(发生异常后不要刷新Session)

来自分类Dev

Grails / GORM:org.hibernate.AssertionFailure:xyz中的null id(发生异常后不要刷新Session)

来自分类Dev

Spring 4 and Hibernate 4/c3p0 with Entity Manager don't start

来自分类Dev

Spring boot session.enableFilter 导致 AssertionFailure: table not found

来自分类Dev

org.hibernate.exception.ConstraintViolationException:列'pacientId'不能为null

来自分类Dev

如果(HttpContext.Current.Session [“ id”]!= null)返回NULL EXCEPTION

来自分类Dev

org.hibernate.exception.SQLGrammarException:无法准备语句-Spring ROO

来自分类Dev

org.hibernate.exception.SQLGrammarException:无法准备语句-Spring ROO

来自分类Dev

Hibernate JPA persist saved child entity with null parent id

来自分类Dev

休眠注释错误(org.hibernate.exception.SQLGrammarException:无法插入:[com.hib.ex.entity.Node])

来自分类Dev

HibernateTemplate抛出java.lang.NoSuchMethodError:org.hibernate.Session.getFlushMode()-Spring4.2.6,Hibernate5.2

来自分类Dev

HibernateTemplate抛出java.lang.NoSuchMethodError:org.hibernate.Session.getFlushMode()-Spring4.2.6,Hibernate5.2

来自分类Dev

org.hibernate.id.IdentifierGenerationException:尝试从空的一对一属性分配ID(带有session.merge)

来自分类Dev

How to implement org.hibernate.Session in Scala

来自分类Dev

无法导入org.hibernate.session

来自分类Dev

嵌套的异常是org.hibernate.exception.SQLGrammarException:无法提取ResultSet,Spring4,Hibernate4

来自分类Dev

org.hibernate.exception.ConstraintViolationException:无法插入

来自分类Dev

为什么在Hibernate中的session.delete()之后需要调用session.flush()?

来自分类Dev

Hibernate:org.hibernate.MappingException:未知实体:entity.Item

来自分类Dev

javax.persistence.PersistenceException:org.hibernate.PropertyAccessException:无法通过Entity.id的反射获取器获取字段值

来自分类Dev

为什么Hibernate抛出org.hibernate.exception.LockAcquisitionException?

来自分类Dev

Hibernate create, don't update, don't drop.

来自分类Dev

嵌套的异常是org.hibernate.exception.SQLGrammarException:无法提取ResultSet,Spring4,Hibernate4。请帮帮我

来自分类Dev

Hibernate flush()影响事务

来自分类Dev

如何在Scala中实现org.hibernate.Session

来自分类Dev

org.hibernate.HibernateException:无法实例化默认tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]

来自分类Dev

org.hibernate.HibernateException:无法实例化默认tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]

来自分类Dev

Spring + Hibernate:没有Hibernate Session绑定到线程

来自分类Dev

org.hibernate.exception.SQLGrammarException:无法插入我正在

Related 相关文章

  1. 1

    Spring JPA / Hibernate org.hibernate.AssertionFailure:实体中的id为null(发生异常后不要刷新Session)

  2. 2

    Grails / GORM:org.hibernate.AssertionFailure:xyz中的null id(发生异常后不要刷新Session)

  3. 3

    Spring 4 and Hibernate 4/c3p0 with Entity Manager don't start

  4. 4

    Spring boot session.enableFilter 导致 AssertionFailure: table not found

  5. 5

    org.hibernate.exception.ConstraintViolationException:列'pacientId'不能为null

  6. 6

    如果(HttpContext.Current.Session [“ id”]!= null)返回NULL EXCEPTION

  7. 7

    org.hibernate.exception.SQLGrammarException:无法准备语句-Spring ROO

  8. 8

    org.hibernate.exception.SQLGrammarException:无法准备语句-Spring ROO

  9. 9

    Hibernate JPA persist saved child entity with null parent id

  10. 10

    休眠注释错误(org.hibernate.exception.SQLGrammarException:无法插入:[com.hib.ex.entity.Node])

  11. 11

    HibernateTemplate抛出java.lang.NoSuchMethodError:org.hibernate.Session.getFlushMode()-Spring4.2.6,Hibernate5.2

  12. 12

    HibernateTemplate抛出java.lang.NoSuchMethodError:org.hibernate.Session.getFlushMode()-Spring4.2.6,Hibernate5.2

  13. 13

    org.hibernate.id.IdentifierGenerationException:尝试从空的一对一属性分配ID(带有session.merge)

  14. 14

    How to implement org.hibernate.Session in Scala

  15. 15

    无法导入org.hibernate.session

  16. 16

    嵌套的异常是org.hibernate.exception.SQLGrammarException:无法提取ResultSet,Spring4,Hibernate4

  17. 17

    org.hibernate.exception.ConstraintViolationException:无法插入

  18. 18

    为什么在Hibernate中的session.delete()之后需要调用session.flush()?

  19. 19

    Hibernate:org.hibernate.MappingException:未知实体:entity.Item

  20. 20

    javax.persistence.PersistenceException:org.hibernate.PropertyAccessException:无法通过Entity.id的反射获取器获取字段值

  21. 21

    为什么Hibernate抛出org.hibernate.exception.LockAcquisitionException?

  22. 22

    Hibernate create, don't update, don't drop.

  23. 23

    嵌套的异常是org.hibernate.exception.SQLGrammarException:无法提取ResultSet,Spring4,Hibernate4。请帮帮我

  24. 24

    Hibernate flush()影响事务

  25. 25

    如何在Scala中实现org.hibernate.Session

  26. 26

    org.hibernate.HibernateException:无法实例化默认tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]

  27. 27

    org.hibernate.HibernateException:无法实例化默认tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]

  28. 28

    Spring + Hibernate:没有Hibernate Session绑定到线程

  29. 29

    org.hibernate.exception.SQLGrammarException:无法插入我正在

热门标签

归档