0

I'm Using hibernate 4 as jpa provider. In my code I insert a new version of report (to PactRegister), select all version of this report, remove child records (ActRegister), And calculate current active version of report with insert a child record. But action remove child and insert child for same parent record throw exception. What wrong?

And I'm have a error message (deleted object would be re-saved by cascade):

 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)

My Entity:

       @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 + " ]";
        }
    }

my repository:

    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;
        }
    }

Logic: Next action execute in one transaction:

        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);

   )
asu
  • 51
  • 1
  • 8
  • Can you show the code and mapping of your `ActRegister` class ? – benzonico Oct 26 '13 at 13:42
  • I am not sure whether this will work or not. Comment out this.setActRegister(null) and call merge. Let the other statement be there. Here, the question is about who is the relationship owner and cascade functions are triggered by relationship owner. – Abhijith Nagarajan Oct 26 '13 at 13:44
  • @Abhijith Nagarajan Thank you for responce. The owner of relation - PactRegister. This construction is work (almost). I'm solved truble - I changed the algorithm and now I do not delete child entity if it will be to inserting later. But this is not a good solution – asu Oct 26 '13 at 16:15
  • @benzonico Thank you for responce. I'm not have mapping ActRegister class. ActRegister it's object view on Act_Register db table (one field - Id, where Id it's foreign key on PactRegister table. ) – asu Oct 26 '13 at 16:22

0 Answers0