2 Replies Latest reply on Sep 21, 2006 10:11 AM by raistlinmolina

    Very Weird, Triplicated childs at runtime, all ok in the DB

    raistlinmolina

      Hello, I have (among other entities) one parent Entity called reportInstance and one child Entity Called reportParameterValue, the relation is OneToMany.

      I have a strange problem that arised becauce I couldn't delete a parent object, when I tired to delete it's child I couldn't either.

      Then I noticed that when I asked the parent for its childs I got them triplicated, all is ok in the database (childs not triplicated).

      The child was a weak entity, having its PK formed by the PK of two tables, when I noticed this problem I tried:

      *Adding an id filed as PK, now the child Entoty has it own pk (the former fileds forming the pk remain as Foreign Keys).
      This didn't solve the problem, I couldn't delete anythimg and still got triplicated entries.

      *Mapping the relationship in both sides, at first I had only mapped it at the Parent side as I didn't want to know a parent from the child.
      This has solved the deletion problem but I still have triplicated childs!!!

      I copy code snippets below:


      The relation at ReportParameterValueEJB.java (the child)

      @ManyToOne (targetEntity = ReportInstanceEJB.class, fetch = FetchType.EAGER)
       @JoinColumn (name = "idReportInstance", insertable=false, updatable=false)
       public ReportInstanceEJB getReportInstance(){
       return this.reportInstance;
       }
      
       public void setReportInstance(ReportInstanceEJB reportInstance){
       this.reportInstance = reportInstance;
       this.idReportInstance = reportInstance.getId();
       }
      


      The relation at ReportInstanceEJB.java (the parent)

      /**
       * Returns the value of the <code>reportParameterValue</code> relation property.
       *
       * @return the value of the <code>reportParameterValue</code> relation property.
       */
       @OneToMany(mappedBy="reportInstance", cascade= CascadeType.MERGE, fetch = FetchType.EAGER)
       public Collection <ReportParameterValueEJB> getReportParameterValues(){
       return parameterValues;
       }
      
       /**
       * Sets the value of the <code>reportParameterValue</code> relation property.
       *
       * @param parameters a value for <code>reportParameterValue</code>.
       */
       public void setReportParameterValues(Collection <ReportParameterValueEJB> parameters) {
       this.parameterValues = parameters;
       }


      And now the traces I'm getting in the JBoss console:

      10:36:57,612 INFO [STDOUT] Number of values:9
      10:36:57,612 INFO [STDOUT] predelete: 10; 10; 2; 27
      10:36:57,628 INFO [STDOUT] postdelete: 27
      10:36:57,628 INFO [STDOUT] predelete: 10; 10; 2; 27
      10:36:57,628 INFO [STDOUT] postdelete: 27
      10:36:57,628 INFO [STDOUT] predelete: 10; 10; 2; 27
      10:36:57,628 INFO [STDOUT] postdelete: 27
      10:36:57,628 INFO [STDOUT] predelete: 12; 10; 2; 45
      10:36:57,628 INFO [STDOUT] postdelete: 45
      10:36:57,628 INFO [STDOUT] predelete: 12; 10; 2; 45
      10:36:57,628 INFO [STDOUT] postdelete: 45
      10:36:57,628 INFO [STDOUT] predelete: 12; 10; 2; 45
      10:36:57,628 INFO [STDOUT] postdelete: 45
      10:36:57,628 INFO [STDOUT] predelete: 13; 10; 2; 45
      10:36:57,628 INFO [STDOUT] postdelete: 45
      10:36:57,628 INFO [STDOUT] predelete: 13; 10; 2; 45
      10:36:57,628 INFO [STDOUT] postdelete: 45
      10:36:57,628 INFO [STDOUT] predelete: 13; 10; 2; 45
      10:36:57,628 INFO [STDOUT] postdelete: 45
      ##########################################
      10:42:59,471 INFO [STDOUT] Number of values:3
      10:42:59,471 INFO [STDOUT] predelete: 16; 15; 2; 27
      10:42:59,471 INFO [STDOUT] postdelete: 27
      10:42:59,471 INFO [STDOUT] predelete: 16; 15; 2; 27
      10:42:59,471 INFO [STDOUT] postdelete: 27
      10:42:59,471 INFO [STDOUT] predelete: 16; 15; 2; 27
      10:42:59,471 INFO [STDOUT] postdelete: 27


      I explain the trace:
      10:42:59,471 INFO [STDOUT] predelete: 16; 15; 2; 27
      I call a println with: the childs id (PK) - 16, the childs FK to the report - 15 the childs id to another parent table - 2, and another field containing its value - 27
      Then I call manager.remove(child);
      and call an println with just its value just to make sure it was deleted without exceptiosn inside.

      10:42:59,471 INFO [STDOUT] postdelete: 27

      Here I deleted two different ReportInstances, id=10, and id=15 respectively.
      Id=10 had 3 actual childs, and in the trace it says that it has nine
      Id=15 had 1 actual child, and in the trace it says that it has three


      The code at the agentBean that performs the ReportInstance deletion is:

      public void deleteReportInstance(ReportInstanceEJB reportInstance) {
       Collection <ReportParameterValueEJB> values = reportInstance.getReportParameterValues();
       Iterator <ReportParameterValueEJB> valuesIt = values.iterator();
       System.out.println("Number of values:" + values.size());
       while (valuesIt.hasNext()){
       ReportParameterValueEJB value = valuesIt.next();
       System.out.println("predelete: " + value.getId()+"; "+ value.getIdReportInstance()+"; "+ value.getIdParameter()+"; "+value.getValue());
       manager.remove(value);
       System.out.println("postdelete: " + value.getValue());
       }
      
       manager.remove(reportInstance);
       }


      I get one instance in the client, get a reference to the agentbean and ask it to delete the reportInstance as show above.

      I have checked the database and I had only one child for reportInstance 10 and three for instance 15.

      What's happening???


      Thanks in advance

        • 1. Re: Very Weird, Triplicated childs at runtime, all ok in the
          raistlinmolina

          I have tired with the other parent (ParameterEJB) and form this side childs are ok, no triplicated entries.

          I copy the code from ParameterEJB.java below

           @OneToMany (mappedBy = "parameter")
           public Set<ReportParameterValueEJB> getReportParameterValues(){
           return this.reportParameterValues;
           }
          
           /**
           * Sets the value of the <code>events</code> property.
           *
           * @param events the value for the <code>events</code> property
           */
           public void setReportParameterValues(Set<ReportParameterValueEJB> reportParameterValues){
           this.reportParameterValues = reportParameterValues;
           }
          


          And now the corresponding side at ReportParameterValueEJB.java

          @ManyToOne (targetEntity = ParameterEJB.class, fetch = FetchType.EAGER)
           @JoinColumn (name = "idParameter", insertable=false, updatable=false)
           public ParameterEJB getParameter(){
           return this.parameter;
           }
          
           public void setParameter(ParameterEJB parameter){
           this.parameter = parameter;
           this.idParameter = parameter.getId();
           }
          


          now the code at the client:
           ParameterEJB parameter = remote.getParameterByPK(1);
          
          
           if (parameter != null){
           System.out.println(parameter.getName());
           delete(parameter);
           }
           parameter = remote.getParameterByPK(2);
           if (parameter != null){
           System.out.println("Options: " + parameter.getParameterOptions().size());
           if (parameter.getParameterOptions().size() > 0){
           System.out.println("Option1: " + parameter.getParameterOptions().iterator().next().getOptionvalue());
           }
           Iterator <ReportParameterValueEJB> rpvs = parameter.getReportParameterValues().iterator();
           System.out.println("Valores asignados: " + parameter.getReportParameterValues().size());
           while ( rpvs.hasNext()){
           ReportParameterValueEJB rpv = rpvs.next();
           System.out.println("Valor asignado: " + rpv.getId()+" valor:" + rpv.getValue());
           }
          
           }
          


          And the output

          Parameter created, Id:17
          Options: 0
          Values: 14
          Value PK: 3 value:27
          Value PK: 7 value:27
          Value PK: 18 value:27
          Value PK: 19 value:27
          Value PK: 11 value:27
          Value PK: 2 value:27
          Value PK: 14 value:27
          Value PK: 1 value:27
          Value PK: 17 value:27
          Value PK: 4 value:27
          Value PK: 6 value:27
          Value PK: 5 value:27
          Value PK: 15 value:34
          Value PK: 8 value:27
          
          



          This relation works ok, the parameter with PK=2 has 14 childs, as the code shows.

          Now, I don't understand why the other relations triplicates the childs!!!, they are the same type, they are coded equal..........

          Please, If anyone sees the difference or something i'm doing wrong......

          Thanks in advance.

          • 2. Re: Very Weird, Triplicated childs at runtime, all ok in the
            raistlinmolina

            Finally I managed to fix the problem myself.

            It seems that Collections are not very well managed and you can expect some issues, I run into de Fetch.EARLY problem when you have more than one ManyToMany or OneToMany relation in the same entity, it happens that you can only have one EARLY if you used Collections, instead if you use Sets all goes fine.

            I've finally noticed that in the second case i Posted I was using a Set to hold the childs, so In changed Collection (ArrayList) to Set (hashSet) in the case that was failing And now it works.

            It seems to me that the 3 objects are in fact the same, in a set if you add the same object more than once it's not added (because it's a set :) ).

            It arises the issue that I was asking the manager to remove the same entity three times and it didn't failed. Maybe as it seems to work in batches only one actual removla is performed.