Hibernate 异常后 Hibernate 不回滚本机生成的 ID

Posted

技术标签:

【中文标题】Hibernate 异常后 Hibernate 不回滚本机生成的 ID【英文标题】:Hibernate does not rollback natively generated ID after Hibernate Exception 【发布时间】:2014-02-22 07:17:26 【问题描述】:

我的事务服务中有一个方法可以验证对象并保存它。在此保存期间,假设由于“子”对象中的垃圾数据 - 引发了 DataException。

这是一个 RuntimeException,Hibernate 会触发回滚。这是我从日志中验证的,如下所示。

当我在 Action 中捕获异常时,我看到 Session 中的“子”对象有一个与之关联的标识符。为什么会这样?

当用户更正值并尝试再次保存对象并且休眠尝试更新对象时会导致问题抛出 Batch update StaleStateException。

我找到了一个描述确切问题的博客 http://www.jroller.com/hasant/entry/hibernate_saveorupdate_trap_for_web 。有没有我想念的解决方案?是否使用合并出路? hibernate.use_identifier_rollback=true 会有帮助吗?

代码

public @Component("action") @Scope("prototype") class Action 
  private @Autowired Service service;
  public void save() 
    try 
      A parent = new A();
      B child = new B();
      child.setValue(2782375983275837583758375); // Data Truncation will be thrown
      service.save(parent, child);
     catch(Exception e) 
      // Why does "child" have an id after rollback?
    
  


public @Service @Transactional(rollbackFor = Exception.class) class ServiceImpl implements Service 
  private @Autowired GeneralDAO generalDao;

  public void save(A parent, B child) throws Exception 
    child.setParent(parent);
    removeExistingGrandChildren(child);
    child.setGrandChildren(new LinkedHashSet<C>());
    C grandChild = new C(something);
    generalDao.saveOrUpdate(child); // cascades and saves grandChildren also.
  

  private void removeExistingGrandChildren(B child) throws Exception 
    if(child.getId() != null) 
      Collection<C> grandChildren = loadGrandChildren(child.getId());
      for(C grandChild : grandChildren) 
        generalDao.delete(grandChild);
      
    
  


public @Repository("generalDao") class GeneralDAOImpl implements GeneralDao 
  private @Autowired SessionFactory sessionFactory;

  protected SessionFactory getSessionFactory() 
    return sessionFactory;
  

  protected void setSessionFactory(SessionFactory sessionFactory) 
    this.sessionFactory = sessionFactory;
  

  @Override
  public Object saveOrUpdate(Object bean) 
    Session session = getSession();
    session.saveOrUpdate(bean);
    return bean;
  

  protected Session getSession() 
    Session currentSession = getSessionFactory().getCurrentSession();
    return currentSession;
  

映射

<class name="com.xxx.model.A" table="A">        
  <id name="id" type="java.lang.Integer" column="id">
    <generator class="native"></generator>
  </id>
  <set name="children" inverse="true" lazy="true" table="B" cascade="save-update">
    <key column="a_Id"/>
    <one-to-many class="com.xxx.model.B" />
  </set>
  <property name="p0" type="java.lang.Integer" column="p0" />
</class>

<class name="com.xxx.model.B" table="B">        
  <id name="id" type="java.lang.Integer" column="id">
    <generator class="native"></generator>
  </id>
  <many-to-one name="parent" class="com.xxx.model.A" fetch="join" lazy="false" column="a_Id" />
  <set name="grandchildren" inverse="true" lazy="true" table="C" cascade="save-update">
    <key column="b_Id"/>
    <one-to-many class="com.xxx.model.C" />
  </set>
  <property name="p1" type="java.lang.Integer" column="p1" />
</class>

<class name="com.xxx.model.C" table="C">        
  <id name="id" type="java.lang.Integer" column="id">
    <generator class="native"></generator>
  </id>
  <many-to-one name="child" class="com.xxx.model.B" fetch="join" lazy="false" column="b_Id" />
  <property name="p2" type="java.lang.Integer" column="p2" />
</class>

堆栈跟踪

13:53:08,474 DEBUG org.hibernate.engine.spi.ActionQueue  - Executing identity-insert immediately
13:53:08,474 DEBUG org.hibernate.SQL  - 
    insert into dbo.B(p1) values (?)
13:53:08,482 DEBUG org.hibernate.id.IdentifierGeneratorHelper  - Natively generated identity: 6581
13:53:08,483 DEBUG org.hibernate.engine.spi.ActionQueue  - Executing identity-insert immediately
13:53:08,483 DEBUG org.hibernate.SQL  - 
    insert into dbo.C(p2) values (?)
13:53:08,487 DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper  - Data truncation [n/a]
java.sql.DataTruncation: Data truncation
    at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:379)
    at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2781)
    at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2224)
    at net.sourceforge.jtds.jdbc.TdsCore.getMoreResults(TdsCore.java:628)
    at net.sourceforge.jtds.jdbc.JtdsStatement.processResults(JtdsStatement.java:525)
    at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQL(JtdsStatement.java:487)
    at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeUpdate(JtdsPreparedStatement.java:421)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:233)
    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:601)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
    at $Proxy42.executeUpdate(Unknown Source)
    at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:96)
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:58)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2936)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3447)
    at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
    at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:203)
    at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:183)
    at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:167)
    at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:320)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:204)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:189)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:114)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
    at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:727)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:719)
    at org.hibernate.engine.spi.CascadingAction$5.cascade(CascadingAction.java:258)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:383)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:412)
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:353)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:329)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:448)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:293)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:204)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:189)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:114)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
    at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:727)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:719)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:715)
    at com.xxx.dao.GeneralDao.saveOrUpdate(GeneralDao.java:59)
    at com.xxx.service.ServiceImpl.save(ServiceImpl.java:727)
    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:601)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy33.save(Unknown Source)
    at com.xxx.action.Action.save(Action.java:433)
    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:601)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:450)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:289)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:252)
    at com.xxx.interceptor.RequestInfoInterceptor.intercept(RequestInfoInterceptor.java:52)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
    at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:249)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:325)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
    at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:546)
    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:399)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:411)
    at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:278)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:411)
    at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:411)
    at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:411)
    at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:411)
    at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:188)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:931)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
13:53:08,502 WARN  org.hibernate.engine.jdbc.spi.SqlExceptionHelper  - SQL Error: 0, SQLState: 22001
13:53:08,502 ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper  - Data truncation
13:53:08,502 WARN  org.hibernate.engine.jdbc.spi.SqlExceptionHelper  - SQL Error: 8115, SQLState: 22003
13:53:08,502 ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper  - Arithmetic overflow error converting numeric to data type numeric.
13:53:08,503 DEBUG org.springframework.orm.hibernate4.HibernateTransactionManager  - Initiating transaction rollback
13:53:08,504 DEBUG org.springframework.orm.hibernate4.HibernateTransactionManager  - Rolling back Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.xxx.model.B#6581]],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
13:53:08,504 DEBUG org.hibernate.engine.transaction.spi.AbstractTransactionImpl  - rolling back
13:53:08,504 DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction  - rolled JDBC Connection
13:53:08,504 DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction  - re-enabling autocommit
13:53:08,505 DEBUG org.springframework.orm.hibernate4.HibernateTransactionManager  - Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.xxx.model.B#6581]],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] after transaction
13:53:08,505 DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl  - Releasing JDBC connection
13:53:08,505 DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl  - Released JDBC connection
13:53:08,505 DEBUG org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler  - HHH000163: Logical connection releasing its physical connection

【问题讨论】:

当版本号或时间戳检查失败时抛出,表明 Session 包含过时的数据(当使用带有版本控制的长事务时)。如果我们尝试删除或更新不存在的行,也会发生这种情况。请注意,此异常通常表明用户未能为类指定正确的未保存值策略! this @Rat-a-tat-a-tat Ratatouille - 注意:我不是在问为什么会发生 StaleStateException。我问为什么回滚后没有删除导致 StaleStateException 的标识符。其次,作为 Integer 的 id 默认情况下应该将 unsaved-value 设置为 null。 为清晰起见编辑了标题 【参考方案1】:

查看类似问题的答案:It's not a bug, but a feature

总的来说,生成id的过程是无事务的,所以即使发出回滚,生成的id也不会'未生成'。

我有基本相同的问题,我尝试设置 hibernate.use_identifier_rollback=true 但无济于事。该属性的文档指出,如果实体被删除,Hibernate 将清除 id,但事实并非如此。

当我知道它是一个新实体时,我使用persist() 解决了这个问题,否则使用merge()。请注意,即使您的实体已经生成了 id,persist() 也会起作用。

【讨论】:

以上是关于Hibernate 异常后 Hibernate 不回滚本机生成的 ID的主要内容,如果未能解决你的问题,请参考以下文章

org.hibernate.AssertionFailure: [...] 条目中的空 id(发生异常后不要刷新会话)

如何解决异常:表 'DBNAME.hibernate_sequence' 不存在

升级Hibernate5,捕捉异常遇到的坑!

org.hibernate.lazyinitialization 异常

hibernate(nested transactions not supported)异常

jpa在save失败后service端catch不到异常原因(Hibernate的一级缓存)