8 Replies Latest reply on Sep 20, 2007 8:11 AM by Thomas Trepper

    CascadeType.PERSIST question

    Thomas Trepper Newbie

      Hi all,

      I am running into troubles with the cascdetype, Please imagine the following szenario:

      SQL (tables)

      CREATE TABLE Party (
       PartyID BIGINT DEFAULT nextval('seq_PartyID') NOT NULL,
       CONSTRAINT PK_Party PRIMARY KEY (PartyID)
      );
      
      CREATE TABLE PartyIsPerson (
       PartyIDPerson BIGINT NOT NULL,
       Forename CHARACTER VARYING(80) NOT NULL,
       Lastname CHARACTER VARYING(80) NOT NULL,
       CONSTRAINT PK_PartyIsPerson PRIMARY KEY (PartyIDPerson)
      );
      
      CREATE TABLE PersonHasCustomization (
       PartyIDPerson BIGINT NOT NULL,
       Locale CHARACTER VARYING(5),
       CONSTRAINT PK_PersonHasCustomization PRIMARY KEY (PartyIDPerson)
      );


      The Party-class ist declared with @Inheritance(strategy=InheritanceType.JOINED)

      and the PartyIsPerson extends from it.


      package com.auctonova.ejb.persistence;
      
      import java.io.Serializable;
      import java.sql.Date;
      
      import javax.persistence.Entity;
      import javax.persistence.OneToOne;
      import javax.persistence.PrimaryKeyJoinColumn;
      import javax.persistence.CascadeType;
      
      @Entity
      @PrimaryKeyJoinColumn(name="partyidperson", referencedColumnName="partyid")
      public class PartyIsPerson extends Party implements Serializable {
       private static final long serialVersionUID = 1L;
       private String forename;
       private String lastname;
       private PersonHasCustomization customization;
      
       //--------------------------------------------------------------------------
       public String getForename() {
       return this.forename;
       }
      
       //--------------------------------------------------------------------------
       public void setForename(String forename) {
       this.forename = forename;
       }
      
       //--------------------------------------------------------------------------
       public String getLastname() {
       return this.lastname;
       }
      
       //--------------------------------------------------------------------------
       public void setLastname(String lastname) {
       this.lastname = lastname;
       }
      
       //--------------------------------------------------------------------------
       @OneToOne(cascade=CascadeType.PERSIST)
       @PrimaryKeyJoinColumn(name="partyidperson", referencedColumnName="partyidperson")
       public PersonHasCustomization getCustomization() {
       return this.customization;
       }
      
       //--------------------------------------------------------------------------
       public void setCustomization(PersonHasCustomization customization) {
       this.customization = customization;
       }
      }
      


      When I am now trying to execute the following code in a bean
      PartyIsPerson p = new PartyIsPerson();
      p.setUsername("Guest"); //Guest
      p.setPassword("Guest"); //Guest
      p.setForename("Guest"); //Guest
      p.setLastname("Guest"); //Guest
      p.setPartyId(100);
      
      PersonHasCustomization phc = new PersonHasCustomization();
      phc.setLocale("DE_de");
      p.setCustomization(phc);
      
      EntityManager.persist(p)


      than I get the following error:
      11:19:28,953 ERROR [JDBCExceptionReporter] Batch-Eintrag 0 insert into PersonHasCustomization (locale, pm_forward_to, partyidperson) values (DE_de, NULL, 0) wurde abgebrochen. Rufen Sie 'getNextException' auf, um die Ursache zu erfahren.
      11:19:28,953 WARN [JDBCExceptionReporter] SQL Error: 0, SQLState: 23503
      11:19:28,953 ERROR [JDBCExceptionReporter] ERROR: insert or update on table "personhascustomization" violates foreign key constraint "partyisperson_personhascustomization"
       Detail: Key (partyidperson)=(0) is not present in table "partyisperson".
      11:19:28,953 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session


      In my opinion this part of the exception
      Detail: Key (partyidperson)=(0) is not present in table "partyisperson"
      means, that something is wrong with the Primary-keys, of course there is no person with the id=0, but i want the EntityManager automatically to assign the customisation the SAME id (in this case 100), before inserting both.

      Does anybody has an idea, what i am doing wrong?

      Thank you very much for help and kind regards,

      Thomas

        • 1. Re: CascadeType.PERSIST question
          wayne baylor Apprentice

          what does your PartyHasCustomization entity look like?

          • 2. Re: CascadeType.PERSIST question
            Thomas Trepper Newbie

            Hi waynebylor,

            thank you for your answer - sorry, i forget to attach the code. Here it is:

            package com.auctonova.ejb.persistence;
            
            import java.io.Serializable;
            
            import javax.persistence.Entity;
            import javax.persistence.Column;
            import javax.persistence.Id;
            import javax.persistence.Table;
            
            
            @Entity
            @Table(name="PersonHasCustomization")
            public class PersonHasCustomization implements Serializable {
             private static final long serialVersionUID = 1L;
             private String locale;
             private long partyidperson;
            
             //--------------------------------------------------------------------------
             public String getLocale() {
             return this.locale;
             }
            
             //--------------------------------------------------------------------------
             public void setLocale(String locale) {
             this.locale = locale;
             }
            
             //--------------------------------------------------------------------------
             @Id
             public long getPartyidperson() {
             return this.partyidperson;
             }
            
             //--------------------------------------------------------------------------
             public void setPartyidperson(long partyidperson) {
             this.partyidperson = partyidperson;
             }
            }
            


            I have still not found the solution. Thank you for your help.

            Thomas

            • 3. Re: CascadeType.PERSIST question
              wayne baylor Apprentice

              so, it looks like your entity code is OK. you just need to add an extra step when saving:

              PartyIsPerson p = new PartyIsPerson();
              p.setUsername("Guest"); //Guest
              p.setPassword("Guest"); //Guest
              p.setForename("Guest"); //Guest
              p.setLastname("Guest"); //Guest
              p.setPartyId(100);
              
              PersonHasCustomization phc = new PersonHasCustomization();
              phc.setPartyidperson(p.getPartyId());
              phc.setLocale("DE_de");
              p.setCustomization(phc);
              
              EntityManager.persist(p)


              from the "Java Persistence w/Hibernate" book it says, JPA doesn't include a standard way of dealing with shared primary key generation. So, it's up to you to set it (page 282).

              • 4. Re: CascadeType.PERSIST question
                Thomas Trepper Newbie

                Thank you very much for your answer - but I think your suggestion will not work, because the Entity PartyIsPerson extends the Entity Party, which has a generated key like this:

                @Id
                 @SequenceGenerator(name="party_id", sequenceName="seq_partyid")
                 @GeneratedValue(generator="party_id", strategy=GenerationType.SEQUENCE)
                 public long getPartyId() {
                 return this.partyid;
                 }


                Therefore when I insert the person, I do not know the key. And therefore i think, that i cannot do the suggested following line
                phc.setPartyidperson(p.getPartyId());


                Do you know, what i mean?
                Any ideas?

                Thanks a lot and kind regards,

                Thomas

                • 5. Re: CascadeType.PERSIST question
                  wayne baylor Apprentice

                  good point, but you are explicitly setting the party id here:

                  p.setPartyId(100);


                  if the id is automatically generated, then you shouldn't be setting the id.

                  • 6. Re: CascadeType.PERSIST question
                    Thomas Trepper Newbie

                    Yes, thats right, in the meanwhile, the line with setting the ID explicitly is removed now. That line was for test-purpose, so now there is only the automatic generation, which is working - still except storing of the nested customization with the same new generated key...

                    Any ideas?

                    • 7. Re: CascadeType.PERSIST question
                      wayne baylor Apprentice

                      ok, then try something like this

                      PartyIsPerson p = new PartyIsPerson();
                      p.setUsername("Guest"); //Guest
                      p.setPassword("Guest"); //Guest
                      p.setForename("Guest"); //Guest
                      p.setLastname("Guest"); //Guest
                      
                      em.persist(p); //will assign an auto generated id
                      
                      PersonHasCustomization phc = new PersonHasCustomization();
                      
                      phc.setPartyidperson(p.getPartyId());
                      
                      phc.setLocale("DE_de");
                      p.setCustomization(phc);
                      
                      em.merge(p);




                      • 8. [SOLVED] CascadeType.PERSIST question
                        Thomas Trepper Newbie

                        Yes, that worked, thank you very much. :-)

                        Thomas