gpt4 book ai didi

java - 在 Hibernate Exception 之后,Hibernate 不会回滚 native 生成的 ID

转载 作者:行者123 更新时间:2023-12-04 11:47:45 25 4
gpt4 key购买 nike

I have a method in my Transactional Service which validates an object and saves it. During this save assume that due to garbage data in the "child" object - a DataException is thrown.

This being a RuntimeException, Hibernate triggers a rollback. This I verified from the logs as shown below.

When I catch the exception in my Action I see that the "child" object in Session has an identifier associated with it. Why is this happening?

This is causing a problem when the user corrects the value and tries to save the object again and hibernate tries to update the object throws a Batch update StaleStateException.

I found a blog which describes the exact problem http://www.jroller.com/hasant/entry/hibernate_saveorupdate_trap_for_web . Is there a solution to this which I'm missing? Is using merge the way out? Will hibernate.use_identifier_rollback=true help?


代码
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

最佳答案

查看类似问题的答案:It's not a bug, but a feature
总之,生成 id 的过程是无事务的,因此即使发出回滚,生成的 id 也不会“未生成”。
我有基本相同的问题,我试过设置 hibernate.use_identifier_rollback=true但无济于事。该属性的文档指出,如果实体被删除,Hibernate 将清除 id,但事实并非如此。
我已经通过使用 persist() 解决了这个问题当我知道它是一个新实体时,merge()除此以外。请注意 persist()即使您的实体已经生成了 id,它也能工作。

关于java - 在 Hibernate Exception 之后,Hibernate 不会回滚 native 生成的 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21448831/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com