无法将数据库状态与会话同步

Posted

技术标签:

【中文标题】无法将数据库状态与会话同步【英文标题】:Could not synchronize database state with session 【发布时间】:2010-06-05 21:58:17 【问题描述】:

我在尝试持久化 ID 为生成值的实体时遇到问题。该实体 (A) 在持久化时必须以级联方式持久存在另一个实体 (B)。 A 和 B 内部的关系是 OneToMany,B 中相关的属性是组合键的一部分。

我正在使用 Eclipse、JBOSS 运行时、JPA/Hibernate

这是我的代码:

实体 A:

@Entity
public class Cambios implements Serializable 
    private static final long serialVersionUID = 1L;

    @SequenceGenerator(name="CAMBIOS_GEN",sequenceName="CAMBIOS_SEQ",allocationSize=1)
    @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CAMBIOS_GEN")
    @Column(name="ID_CAMBIO")
    private Long idCambio;

    //bi-directional many-to-one association to ObjetosCambio
    @OneToMany(cascade=CascadeType.PERSIST,mappedBy="cambios")
    private List<ObjetosCambio> objetosCambioList;  

    public Cambios() 
    

    ...
 

实体 B:

@Entity
@Table(name="OBJETOS_CAMBIO")
public class ObjetosCambio implements Serializable 
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private ObjetosCambioPK id;

    //bi-directional many-to-one association to Cambios
    @ManyToOne
    @JoinColumn(name="ID_CAMBIO", insertable=false, updatable=false)
    private Cambios cambios;

    //bi-directional many-to-one association to Objetos
    @ManyToOne
    @JoinColumn(name="ID_OBJETO", insertable=false, updatable=false)
    private Objetos objetos;

    public ObjetosCambio() 
    

...

实体 B PK:

@Embeddable
public class ObjetosCambioPK implements Serializable 
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    @Column(name="ID_OBJETO")
    private Long idObjeto;

    @Column(name="ID_CAMBIO")
    private Long idCambio;

    public ObjetosCambioPK() 
    

客户:

public String generarCambio()

        ServiceLocator serviceLocator = null;
        try         
            serviceLocator = serviceLocator.getInstance();
            FachadaLocal tcLocal;
            tcLocal = (FachadaLocal)serviceLocator.getFacadeService("java:comp/env/negocio/Fachada"); 

            Cambios cambio = new Cambios();

            Iterator it = objetosLocal.iterator(); //OBJETOSLOCAL IS ALREADY POPULATED OUTSIDE OF THIS METHOD            
            List<ObjetosCambio> ocList = new ArrayList();            
            while (it.hasNext())
                     Objetos objeto = (Objetos)it.next();
                     ObjetosCambio objetosCambio = new ObjetosCambio();
                     objetosCambio.setCambios(cambio); //AT THIS TIME THIS "CAMBIO" DOES NOT HAVE ITS ID, ITS SUPPOSED TO BE GENERATED AT PERSISTENCE TIME

                     ObjetosCambioPK ocPK = new ObjetosCambioPK();
                     ocPK.setIdObjeto(objeto.getIdObjeto());

                     objetosCambio.setId(ocPK); 
                     ocList.add(objetosCambio);
                                  

            cambio.setObjetosCambioList(ocList); 

            tcLocal.persistEntity(cambio); 
            return "exito";            
                 catch (NamingException e) 
                    // TODO                
                    e.printStackTrace();                    
                                            
         return null;
    


ERROR:

15:23:25,717 WARN  [JDBCExceptionReporter] SQL Error: 1400, SQLState: 23000
15:23:25,717 ERROR [JDBCExceptionReporter] ORA-01400: no se puede realizar una inserción NULL en ("CDC"."OBJETOS_CAMBIO"."ID_CAMBIO")

15:23:25,717 WARN  [JDBCExceptionReporter] SQL Error: 1400, SQLState: 23000
15:23:25,717 ERROR [JDBCExceptionReporter] ORA-01400: no se puede realizar una inserción NULL en ("CDC"."OBJETOS_CAMBIO"."ID_CAMBIO")

15:23:25,717 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
    at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:504)
    at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:101)
    at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:269)
    at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:89)
    at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:177)
    at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1423)
    at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:137)
    at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75)
    at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:170)
    at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87)
    at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:190)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
    at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
    at org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
    at org.jboss.ejb3.security.Ejb3AuthenticationInterceptorv2.invoke(Ejb3AuthenticationInterceptorv2.java:186)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
    at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:41)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
    at org.jboss.ejb3.BlockContainerShutdownInterceptor.invoke(BlockContainerShutdownInterceptor.java:67)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
    at org.jboss.aspects.currentinvocation.CurrentInvocationInterceptor.invoke(CurrentInvocationInterceptor.java:67)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
    at org.jboss.ejb3.session.SessionSpecContainer.invoke(SessionSpecContainer.java:176)
    at org.jboss.ejb3.session.SessionSpecContainer.invoke(SessionSpecContainer.java:216)
    at org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerBase.invoke(SessionProxyInvocationHandlerBase.java:207)
    at org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerBase.invoke(SessionProxyInvocationHandlerBase.java:164)
    at $Proxy298.persistEntity(Unknown Source)
    at backing.SolicitudCambio.generarCambio(SolicitudCambio.java:521)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.faces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:146)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:92)
    at javax.faces.component.UICommand.broadcast(UICommand.java:332)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:287)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:401)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:95)
    at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:245)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:110)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:213)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:301)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
    at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.sql.BatchUpdateException: ORA-01400: no se puede realizar una inserción NULL en ("CDC"."OBJETOS_CAMBIO"."ID_CAMBIO")

提前致谢! JM.-


我尝试手动设置 cambios.idCambio,但仍然遇到同样的错误。 Hibernate 应该在 objetosCambioPK.idCambio 和 objetosCambio.cambios 之间做某种映射。也许这就是我在这里缺少的东西,我不知道如何实现它。

有人吗?

【问题讨论】:

【参考方案1】:

我不认为上面的代码可以工作,你的可嵌入ObjetosCambioPKidCambio 根本没有分配,因此数据库错误。实际上我不知道如何以“完全自动化”的方式实现您想要的(我认为这是不可行的),因此我会首先 persist()flush() 新的 Cambios 然后设置分配的Id 在每个 ObjetosCambio 实例的复合键上。

【讨论】:

感谢您的回复,我曾经实现过这一目标,但它使用的是不同的架构(EJB3、Jdeveloper、Toplink),所以我知道这可以工作。当时我使用@IdClass 注释而不是@EmbeddedId,但我读过它不是当今最好的方法,似乎这个@IdClass 只在Hibernate 中实现,因为EJB2 兼容性。除此之外,我也遇到了@idClass 的问题......所以我更愿意继续尝试为此寻找解决方案。关于您的建议: “因此,我将首先对新的 Cambios 进行持久化()和刷新(),然后在每个 ObjetosCambio 实例的复合键上设置分配的 Id。”如果我按照你说的方式这样做,我不会冒着让数据库处于不一致状态的风险吗? (假设在ObjetosCambio持续时间发生异常) @Steppen 如果在ObjetosCambio持续时间发生异常,事务将回滚,您不会处于不一致状态。 是的,ObjetosCambio tx 会回滚,但是 Cambio 呢?这个已经被持久化了......所以我会让实体 Cambio 在没有它对应的 ObjetosCambio 的情况下持久化。也许我可以添加额外的代码来明确地说两者都持久化并且不能分开完成,但这不是我想要的。 @Steppen:我没有关注你。我从不建议运行两个单独的事务,我建议 persistflush Cambio 获取分配的 ID(刷新!= 提交),然后再坚持 ObjetosCambio。所以万一发生异常,一切都会回滚。

以上是关于无法将数据库状态与会话同步的主要内容,如果未能解决你的问题,请参考以下文章

缓存与会话的优势

Oracle11gR2设置连接数process与会话session值

《华为HCIE安全认证》学习笔记 | 状态监测与会话表技术

身份验证:JWT 使用与会话

Oracle数据库的连接模式connection Mode连接connection与会话session

图与会话