賞金明天到期。_ 此問題的答案有資格獲得 50聲望賞金。 FrancescoDS希望引起對這個問題的更多關注。
在我的 Java 專案(Spring MVC)中,我有以下物體:
public class TariffeBaseComposizioni implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "ID")
private Long id;
...
@JoinColumn(name = "TIPO_COMPOSIZIONE", referencedColumnName = "SIGLA")
@ManyToOne
private TipiComposizioni tipoComposizione;
...
}
public class TipiComposizioni implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "ID")
private Long id;
@Size(max = 20)
@Column(name = "SIGLA")
private String sigla;
@Size(max = 255)
@Column(name = "NOME")
private String nome;
...
}
我正在嘗試使用 save() 保存我的 TariffeBaseComposizioni 實體:
getCurrentSession().save(t);
其中“t”的型別為“TariffeBaseComposizioni”。
呼叫 save 時,會引發 HibernateOptimisticLockingFailureException。
這里是錯誤的堆疊跟蹤,其中執行的查詢是可見的:
Hibernate: insert into TARIFFE_BASE_COMPOSIZIONI (ID_FASCIA, PREZZO, PUNTI, TIPO_COMPOSIZIONE, ID) values (?, ?, ?, ?, ?)
Hibernate: update TARIFFE_BASE_COMPOSIZIONI set ID_FASCIA=?, PREZZO=?, PUNTI=?, TIPO_COMPOSIZIONE=? where ID=?
2022-06-10 12:55:02 INFO AbstractBatchImpl:195 - HHH000010: On release of batch it still contained JDBC statements
2022-06-10 12:55:02 ERROR GlobalExceptionHandler:15 - Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:181)
at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:680)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:562)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy163.save(Unknown Source)
at it.openingcode.ep.web.controller.TariffeBaseComposizioniController.doUpdate(TariffeBaseComposizioniController.java:210)
at it.openingcode.ep.web.controller.TariffeBaseComposizioniController.doUpdate(TariffeBaseComposizioniController.java:36)
at it.openingcode.ep.web.AbstractCrudController.update(AbstractCrudController.java:163)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:1025)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1137)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2575)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2564)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:81)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:59)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3224)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3126)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3456)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:364)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:356)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:278)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:328)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:554)
... 80 more
我知道問題是在我的物件中有一個帶有空 id 的 TipiComposizioni 物體(它內部只有 SIGLA 值)。在 Oracle 表中,TIPI_COMPOSIZIONI 具有帶有欄位 SIGLA 的自然鍵。
我已經解決了使用 ID 值從資料庫加載整個 TipiComposizioni 物體的問題,但我想了解 Hibernate 引發該例外的原因以及是否有其他方法可以解決它。我考慮過在模型類中對 JPA 注釋進行一些編輯,但沒有任何效果。
編輯:
這里涉及的兩個 Oracle 表的腳本:
CREATE TABLE TARIFFE_BASE_COMPOSIZIONI
(
ID NUMBER(11),
ID_FASCIA NUMBER(11),
TIPO_COMPOSIZIONE VARCHAR2(20 BYTE),
PREZZO NUMBER(15,5) DEFAULT 0,
PUNTI NUMBER(11) DEFAULT 0
);
CREATE UNIQUE INDEX NK_TARIFFE_BASE_COMPOSIZIONI ON TARIFFE_BASE_COMPOSIZIONI
(ID_FASCIA, TIPO_COMPOSIZIONE);
CREATE UNIQUE INDEX PK_TARIFFE_BASE_COMPOSIZIONI ON TARIFFE_BASE_COMPOSIZIONI
(ID);
ALTER TABLE TARIFFE_BASE_COMPOSIZIONI ADD (
CONSTRAINT PK_TARIFFE_BASE_COMPOSIZIONI
PRIMARY KEY
(ID)
USING INDEX PK_TARIFFE_BASE_COMPOSIZIONI
ENABLE VALIDATE);
ALTER TABLE TARIFFE_BASE_COMPOSIZIONI ADD (
CONSTRAINT FK_TABC_FASC
FOREIGN KEY (ID_FASCIA)
REFERENCES FASCE (ID)
ENABLE VALIDATE,
CONSTRAINT FK_TABC_TICO
FOREIGN KEY (TIPO_COMPOSIZIONE)
REFERENCES TIPI_COMPOSIZIONI (SIGLA)
ENABLE VALIDATE);
---------------
CREATE TABLE TIPI_COMPOSIZIONI
(
ID NUMBER(11),
SIGLA VARCHAR2(20 BYTE) NOT NULL,
NOME VARCHAR2(255 BYTE) NOT NULL
);
CREATE UNIQUE INDEX NK_TIPI_COMPOSIZIONI ON TIPI_COMPOSIZIONI
(SIGLA);
CREATE UNIQUE INDEX PK_TIPI_COMPOSIZIONI ON TIPI_COMPOSIZIONI
(ID);
ALTER TABLE TIPI_COMPOSIZIONI ADD (
CONSTRAINT PK_TIPI_COMPOSIZIONI
PRIMARY KEY
(ID)
USING INDEX PK_TIPI_COMPOSIZIONI
ENABLE VALIDATE,
CONSTRAINT NK_TIPI_COMPOSIZIONI
UNIQUE (SIGLA)
USING INDEX NK_TIPI_COMPOSIZIONI
ENABLE VALIDATE);
編輯2:我在類定義中添加了以下內容(我在寫問題時忘記添加它):
private static final long serialVersionUID = 1L;
serialVersionUID 會影響 save() 程序嗎?
我還注意到 Hibernate 執行 INSERT INTO 查詢,然后嘗試在同一個 TARIFFE_BASE_COMPOSIZIONI 表上執行 UPDATE 查詢。
uj5u.com熱心網友回復:
正如您在問題中所述,問題在于TipiComposizioniid 欄位沒有任何價值。如果您已經在sigla.
由于您沒有以任何方式(例如)指定@IdofTipiComposizioni由資料庫生成,因此@GeneratedValue(strategy = GenerationType.IDENTITY)您必須自己提供 id。所以基本上,你有 3 種方法來解決這個問題:
1:自動生成 id 值TipiComposizioni并添加@GeneratedValue(strategy = GenerationType.IDENTITY)到 id 欄位。這需要您更改資料庫:
public class TipiComposizioni implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // the actual GenerationType can differ
@Basic(optional = false)
@NotNull
@Column(name = "ID")
private Long id;
@Size(max = 20)
@Column(name = "SIGLA")
private String sigla;
@Size(max = 255)
@Column(name = "NOME")
private String nome;
}
2:手動提供id值。您可以保持映射和資料庫原樣,但您必須自己管理 id。
3:正如你所說,private String sigla;已經是一個自然鍵,所以你可以簡單地洗掉@Idfromprivate Long id;并將其添加到private String sigla;. 由于您已經為 提供了一個值sigla,因此您不必擔心更多。
public class TipiComposizioni implements Serializable {
@Basic(optional = false)
@NotNull
@Column(name = "ID")
private Long id;
@Id
@Size(max = 20)
@Column(name = "SIGLA")
private String sigla;
@Size(max = 255)
@Column(name = "NOME")
private String nome;
}
就我個人而言,我會選擇解決方案 3,因為我認為這會導致最少的作業。
uj5u.com熱心網友回復:
我認為導致問題的代碼更多。我正在撰寫的這個解決方案只是一種解決方法,但真正的問題是一個謎,因為我們沒有完整的代碼。getCurrentSession().flush()打完電話就打getCurrentSession().save(t)
getCurrentSession().save(t);
getCurrentSession().flush();
uj5u.com熱心網友回復:
也許將屬性映射sigla為自然識別符號會有所幫助:
public class TipiComposizioni implements Serializable {
private static final long serialVersionUID = 1L;
@Id
// Is this correct? You said the id is null for a row on the db
@Basic(optional = false)
@NotNull
@Column(name = "ID")
private Long id;
@NaturalId
@Size(max = 20)
@Column(name = "SIGLA")
private String sigla;
@Size(max = 255)
@Column(name = "NOME")
private String nome;
...
}
當您更新 TariffeBaseComposizioni 時:
String sigla = ...
TariffeBaseComposizioni tariffe = ...
TipiComposizioni tipo = getCurrentSession()
.bySimpleNaturalId( TipiComposizioni.class )
.getReference(sigla ); // Assuming you know already it exists in the db
tariffe.setTipoComposizione( tipi );
...
我認為當 Hibernate 創建關聯時,某些識別符號為 null 的事實TipiComposizioni會導致問題,使其認為物體在更新關聯時發生了變化(我沒有測驗過這個理論)。
使用getReference不應導致執行任何其他查詢以選擇或更新TipiComposizioni。除非有什么變化tipo(您問題中的更新查詢試圖修改哪一列?)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/494117.html
