在一个事务中更新中删除后出错(已删除的对象将通过级联重新保存)

时间:2013-10-26 13:04:39

标签: hibernate insert cascading-deletes

我正在使用hibernate 4作为jpa提供程序。 在我的代码中,我插入一个新版本的报告(到PactRegister),选择此报告的所有版本,删除子记录(ActRegister),并通过插入子记录计算当前活动版本的报告。 但是动作删除子项并插入相同父记录抛出异常的子项。 怎么了?

我有一条错误消息(已删除的对象将通过级联重新保存):

 ru.sigmasoft.DoMessage.Factory.State.OracleProcess.OracleSenderHandler.handle(OracleSenderHandler.java:73)
            at ru.sigmasoft.DoMessage.Factory.State.OracleProcess.OracleProcessingTemplate.process(OracleProcessingTemplate.java:63)
            at ru.sigmasoft.DoMessage.Oracle.OracleTableListenerImpl.onMessage(OracleTableListenerImpl.java:28)
            at ru.sigmasoft.DoMessage.Oracle.OracleTableConsumer.listen(OracleTableConsumer.java:68)
            at ru.sigmasoft.DoMessage.Oracle.OracleTableConsumer.setMessageListener(OracleTableConsumer.java:35)
            at ru.DbManage.run(DbManage.java:22)
            at java.lang.Thread.run(Thread.java:619)
        Caused by: java.lang.IllegalArgumentException: org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [ru.sigmasoft.DOSrv.Server.domain.VersionSchema.ActRegister#49]
            at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:882)
            at ru.sigmasoft.DOSrv.Server.service.jpa.oraDb.Repository_PactRegister.modify(Repository_PactRegister.java:53)
            at ru.sigmasoft.DOSrv.Server.service.bean.Registration.Registration_Act.registerDocumentVersion(Registration_Act.java:62)
            at ru.sigmasoft.Specification.Message.CMN13011_Handler.handle(CMN13011_Handler.java:74)
            at ru.sigmasoft.DoMessage.Factory.State.OracleProcess.ParseBody.handle(ParseBody.java:107)
            at ru.sigmasoft.DoMessage.Factory.State.OracleProcess.OracleProcessingTemplate.process(OracleProcessingTemplate.java:46)
            ... 5 more
        Caused by: org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [ru.sigmasoft.DOSrv.Server.domain.VersionSchema.ActRegister#49]
            at org.hibernate.internal.SessionImpl.forceFlush(SessionImpl.java:1222)
            at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:177)
            at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136)
            at org.hibernate.ejb.event.EJB3MergeEventListener.saveWithGeneratedId(EJB3MergeEventListener.java:71)
            at org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:236)
            at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:216)
            at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:154)
            at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:910)
            at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:892)
            at org.hibernate.engine.spi.CascadingAction$6.cascade(CascadingAction.java:288)
            at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
            at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
            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.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:439)
            at org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:183)
            at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:157)
            at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:76)
            at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:900)
            at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:884)
            at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:888)
            at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:879)

我的实体:

       @Entity
    @Table(name = "PACT_REGISTER")
    @XmlRootElement
    public class PactRegister implements Serializable {

        private static final long serialVersionUID = 1L;
        // @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
        @Id
        @GenericGenerator(name = "generatorPactR", strategy = "foreign",
                parameters =
                @Parameter(name = "property", value = "edRegister"))
        @GeneratedValue(generator = "generatorPactR")
        @Basic(optional = false)
        @Column(name = "ID")
        private Long id;
        @Column(name = "G071")
        private String g071;
        @Column(name = "G072")
        @Temporal(TemporalType.DATE)
        private Date g072;
        @Column(name = "G073")
        private String g073;
        @Column(name = "G073K")
        private String g073k;
        @Column(name = "SVHLICK")
        private String svhlick;
        @Column(name = "SVHLIC")
        private String svhlic;
        @Column(name = "MODIFICATIONDATETIME")
        @Temporal(TemporalType.DATE)
        private Date modificationdatetime;
        @JoinColumn(name = "ID", referencedColumnName = "ID", insertable = false, updatable = false)
        @OneToOne(optional = false, fetch = FetchType.LAZY)
        private EdRegister edRegister;
        @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true , mappedBy = "pactRegister", fetch = FetchType.LAZY)
        private ActRegister actRegister;

        public PactRegister() {
        }

        public PactRegister(Long id) {
            this.id = id;
        }

        public Long getId() {
            return id;
        }

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

        public String getG071() {
            return g071;
        }

        public void setG071(String g071) {
            this.g071 = g071;
        }

        public Date getG072() {
            return g072;
        }

        public void setG072(Date g072) {
            this.g072 = g072;
        }

        public String getG073() {
            return g073;
        }

        public void setG073(String g073) {
            this.g073 = g073;
        }

        public String getG073k() {
            return g073k;
        }

        public void setG073k(String g073k) {
            this.g073k = g073k;
        }

        public String getSvhlick() {
            return svhlick;
        }

        public void setSvhlick(String svhlick) {
            this.svhlick = svhlick;
        }

        public String getSvhlic() {
            return svhlic;
        }

        public void setSvhlic(String svhlic) {
            this.svhlic = svhlic;
        }

        public Date getModificationdatetime() {
            return modificationdatetime;
        }

        public void setModificationdatetime(Date modificationdatetime) {
            this.modificationdatetime = modificationdatetime;
        }

        public EdRegister getEdRegister() {
            return edRegister;
        }

        public void setEdRegister(EdRegister edRegister) {
            this.edRegister = edRegister;
        }

        public ActRegister getActRegister() {
            return actRegister;
        }

        protected void setActRegister(ActRegister actRegister) {
            this.actRegister = actRegister;
        }

        @Override
        public int hashCode() {
            int hash = 0;
            hash += (id != null ? id.hashCode() : 0);
            return hash;
        }

        @Override
        public boolean equals(Object object) {
            // TODO: Warning - this method won't work in the case the id fields are not set
            if (!(object instanceof PactRegister)) {
                return false;
            }
            PactRegister other = (PactRegister) object;
            if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "Eh_OWNER.PactRegister[ id=" + id + " ]";
        }

        public void removeFromActive(final ActRegister ar) {
            // check for no-op
            if (ar == null /*|| !getActRegister().contains(ar)*/) {
                return;
            }
            // dissociate arg
            //  actRegister=null;
            this.setActRegister(null);
            ar.setPactRegister(null);

            // additional business logic
            //onRemoveFromActive(ar);

        }

        public void addToActive(final ActRegister ar) {
            // check for no-op
            if (ar == null /*|| !getActRegister().contains(ar)*/) {
                return;
            }
            // dissociate arg
            //  actRegister=null;
            setActRegister(ar);
            ar.setPactRegister(this);

            // additional business logic
            //onRemoveFromActive(ar);

        }
and

    @Entity
    @Table(name = "ACT_REGISTER")
    @XmlRootElement
    public class ActRegister implements Serializable {

        private static final long serialVersionUID = 1L;
        // @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
        @Id
        @GenericGenerator(name = "generatorActR", strategy = "foreign",
                parameters =
                @Parameter(name = "property", value = "pactRegister"))
        @GeneratedValue(generator = "generatorActR")
        @Basic(optional = false)
        @Column(name = "ID")
        private Long id;
        @JoinColumn(name = "ID", referencedColumnName = "ID", insertable = false, updatable = false)
        @OneToOne(optional = false, fetch = FetchType.LAZY)
        private PactRegister pactRegister;

        public ActRegister() {
        }

        public ActRegister(Long id) {
            this.id = id;
        }

        public Long getId() {
            return id;
        }

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

        public PactRegister getPactRegister() {
            return pactRegister;
        }

        public void setPactRegister(PactRegister pactRegister) {
            this.pactRegister = pactRegister;
        }

        @Override
        public int hashCode() {
            int hash = 0;
            hash += (id != null ? id.hashCode() : 0);
            return hash;
        }

        @Override
        public boolean equals(Object object) {
            // TODO: Warning - this method won't work in the case the id fields are not set
            if (!(object instanceof ActRegister)) {
                return false;
            }
            ActRegister other = (ActRegister) object;
            if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "Eh_OWNER.ActRegister[ id=" + id + " ]";
        }
    }

我的存储库:

    public class Repository_PactRegister extends GenericRepositoryImpl<PactRegister, Long> {

        public Repository_PactRegister(EntityManager em) {
            super(em);
        }

        public List<PactRegister> findActive(String g071, Date g072, String g073, String g073k, String svhLick, String svhLic) {
            String SELECT_ACTIVE = "select * from PACT_REGISTER a inner join ACT_REGISTER b on a.id=b.id \n"
                    + " where a.g071=:G071 and a.g072=:G072 and a.g073=:G073 and a.g073k=:G073K and a.SVHLICK=:SVHLICK and a.SVHLIC=:SVHLIC";
            Query q = em.createNativeQuery(SELECT_ACTIVE, PactRegister.class);
            q.setParameter("G071", g071);
            q.setParameter("G072", g072, TemporalType.DATE);
            q.setParameter("G073", g073);
            q.setParameter("G073K", g073k);
            q.setParameter("SVHLICK", svhLick);
            q.setParameter("SVHLIC", svhLic);
            q.setParameter("SVHLIC", svhLic);
            List<PactRegister> results = q.getResultList();
            return results;
        }

        public PactRegister findLastByDocIdentifyer(String g071, Date g072, String g073, String g073k, String svhLick, String svhLic) {
            //Поиск записи с максимальной датой модификации для данного отчета
            String SELECT_MAX = "select * from PACT_REGISTER f where f.id=(select max(id) \n"
                    + " from PACT_REGISTER a)";
            Query q = em.createNativeQuery(SELECT_MAX, PactRegister.class);
            List<PactRegister> results = q.getResultList();
            return results.isEmpty() ? null : results.get(0);

        }

        @Override
        public PactRegister modify(PactRegister entity) {
            em.find(PactRegister.class, entity.getId());
            PactRegister mergedPactRegister = em.merge(entity);
            return mergedPactRegister;
        }
    }

逻辑:下一个操作在一个事务中执行:

        private final Repository_EdRegister rer;
        private final Repository_PactRegister rpr;
         ......
          public PactRegister registerDocumentVersion(Act doc, EdRegister edRegister) {
            //insert new record of report
            PactRegister pactRegister = new PactRegister();
            pactRegister.setG071(doc.getG071());
            pactRegister.setG072(doc.getG072());
            pactRegister.setG073(doc.getG073());
            pactRegister.setG073k("0"/*doc.getG073k()*/);
            pactRegister.setSvhlick(doc.getSvhlick());
            pactRegister.setSvhlic(doc.getSvhlic());
            pactRegister.setModificationdatetime(new Date()/*doc.getModificationdatetime()*/);//Lkz ncnbhjdfybz!!
            edRegister.addToPactRegister(pactRegister);
            rpr.create(pactRegister);
    // Get parent records for this report
            List<PactRegister> activeS = rpr.findActive(doc.getG071(), doc.getG072(), doc.getG073(), /*doc.getG073k()*/ "0", doc.getSvhlick(), doc.getSvhlic());
    //remove all childs
            if (pactRegister != null) {
                for (PactRegister active : activeS) {

                    ActRegister ar = active.getActRegister();
                    active.removeFromActive(ar);
                    //   ar = null;
                    rpr.modify(active);

                }
            }


    //Choose active record
            // PactRegister activeCandidate = rpr.findById(PactRegister.class, Long.valueOf("110"));
            PactRegister activeCandidate = rpr.findLastByDocIdentifyer(doc.getG071(), doc.getG072(), doc.getG073(), "0"/*doc.getG073k()*/, doc.getSvhlick(), doc.getSvhlic());
            activeCandidate.addToActive(new ActRegister());
            rpr.modify(activeCandidate);
            return activeCandidate;

    }Exception throws when transaction commit. And only if execute method rpr.findLastByDocIdentifyer (it's call   

     String SELECT_MAX = "select * from PACT_REGISTER f where f.id=(select max(id) \n"
                    + " from PACT_REGISTER a)";
            Query q = em.createNativeQuery(SELECT_MAX, PactRegister.class);
            List<PactRegister> results = q.getResultList();
            return results.isEmpty() ? null : results.get(0);

   )

0 个答案:

没有答案