This discussion is archived
4 Replies Latest reply: Jun 7, 2012 7:13 AM by gimbal2 RSS

When Parent is saved, Child doesnt get saved.

942083 Newbie
Currently Being Moderated
Hi,
I have 2 entities

public Parent()
{
int A;
int B;
Child child;

@ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
     @JoinColumn(name = "child_id", nullable = false)
     public Child getChild() {
          return this.child;
     }
}

public Child()
{
int child_Id;
int Y;
Set<Parent> parents;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "child")
     public Set<Parent> getParents() {
          return this.parents;
     }

}

Then
Parent P = new Parent();
Child c = new Child();
....
I set values for both parent and child classes
p.setChild(c);

So when i save parent class

entityManager.persist(parent);

Ideally it should save the child. But it get the following error. My Entity Mapping were not manually written. They were generated by eclipse. So i presume as long as the database mapping is correct by entity mapping will also be correct.

+
Caused by: <openjpa-1.1.1-SNAPSHOT-r422266:807362 nonfatal store error> org.apache.openjpa.util.StoreException: ORA-02291: integrity constraint (PARENT_R03) violated - parent key not found
{prepstmnt 4234 INSERT INTO PARENT (A,B, CHILD_ID) VALUES (?, ?, ?, ?, ?, ?, ?) [ (null) null, (null) null, (BigDecimal) 58608]} [code=2291, state=23000]
FailedObject: com.ejb.entity.Parent@337261
     at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4207)
     at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4171)
     at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:102)
     at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:72)
     at kodo.jdbc.kernel.BatchingPreparedStatementManager.flushInternal(BatchingPreparedStatementManager.java:214)
     at kodo.jdbc.kernel.BatchingPreparedStatementManager.flushInternal(BatchingPreparedStatementManager.java:112)
     at kodo.jdbc.kernel.BatchingPreparedStatementManager.flush(BatchingPreparedStatementManager.java:72)
     at kodo.jdbc.kernel.AutoOrderUpdateManager.flush(AutoOrderUpdateManager.java:84)
     at kodo.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:68)
     at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:89)
     at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:72)
     at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:549)
     at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:130)
     at org.apache.openjpa.datacache.DataCacheStoreManager.flush(DataCacheStoreManager.java:554)
     at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:130)
     ... 49 more
     +
     As you can see the CHILD_ID as been generated. But I think the order in which it gets commited is different. Please let me know if I need to change the configuration of my entity to make this work.
  • 1. Re: When Parent is saved, Child doesnt get saved.
    942083 Newbie
    Currently Being Moderated
    Please note that the primary keys for both the are generated by sequence. like below

    @Id
         @SequenceGenerator(name="CHILD_ID_GENERATOR", sequenceName="CHILD_SEQ")
         @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CHILDID_GENERATOR")

    I am using a javax.persistence.Entity class.
  • 2. Re: When Parent is saved, Child doesnt get saved.
    gimbal2 Guru
    Currently Being Moderated
    So you only posted half the entities? The error message does not seem to agree with you on there being an @Id column as far as I can tell.

    Also the relationship is quite backwards; a parent tends to have many children, not the other way around.
  • 3. Re: When Parent is saved, Child doesnt get saved.
    942083 Newbie
    Currently Being Moderated
    I thought Parents have many children.Sorry if my example was confusing....Here are the real entities....


    @Entity
    @Table(name = "Table1")
    public class RfuiRfLgcMap implements java.io.Serializable {

         // Fields

         /**
         *
         */
         private static final long serialVersionUID = 8921402679423314771L;
         private BigDecimal rfLgcMapId;
         private RfuiRfDef rfuiRfDef;
         private Timestamp creatTs;
         private String creatByUsrid;
         private Timestamp updtTs;
         private String updtByUsrid;

         // Constructors

         /** default constructor */
         public RfuiRfLgcMap() {
         }

         /** minimal constructor */
         public RfuiRfLgcMap(BigDecimal rfLgcMapId) {
              this.rfLgcMapId = rfLgcMapId;
         }

         // Property accessors
         @Id
         @SequenceGenerator(name="ID_GENERATOR", sequenceName="ID_SEQ")
         @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="MAPID_GENERATOR")
         @Column(name = "RF_LGC_MAP_ID", unique = true, nullable = false, precision = 22, scale = 0)
         public BigDecimal getRfLgcMapId() {
              return this.rfLgcMapId;
         }

         public void setRfLgcMapId(BigDecimal rfLgcMapId) {
              this.rfLgcMapId = rfLgcMapId;
         }

         @ManyToOne(cascade=CascadeType.ALL,fetch = FetchType.EAGER )
         @JoinColumn(name = "RF_ID")
         public RfuiRfDef getRfuiRfDef() {
              return this.rfuiRfDef;
         }

         public void setRfuiRfDef(RfuiRfDef rfuiRfDef) {
              this.rfuiRfDef = rfuiRfDef;
         }

         @Column(name = "CREAT_TS", length = 11)
         public Timestamp getCreatTs() {
              return this.creatTs;
         }

         public void setCreatTs(Timestamp creatTs) {
              this.creatTs = creatTs;
         }

         @Column(name = "CREAT_BY_USRID", length = 10)
         public String getCreatByUsrid() {
              return this.creatByUsrid;
         }

         public void setCreatByUsrid(String creatByUsrid) {
              this.creatByUsrid = creatByUsrid;
         }

         @Column(name = "UPDT_TS", length = 11)
         public Timestamp getUpdtTs() {
              return this.updtTs;
         }

         public void setUpdtTs(Timestamp updtTs) {
              this.updtTs = updtTs;
         }

         @Column(name = "UPDT_BY_USRID", length = 10)
         public String getUpdtByUsrid() {
              return this.updtByUsrid;
         }

         public void setUpdtByUsrid(String updtByUsrid) {
              this.updtByUsrid = updtByUsrid;
         }
    }


    @Entity
    @Table(name = "TABLE2")
    public class RfuiRfDef implements java.io.Serializable {

         // Fields

         /**
         *
         */
         private static final long serialVersionUID = 2710263518182989628L;
         private BigDecimal rfId;
         private String rfCd;
         private String modifiedFlg;
         private Timestamp creatTs;
         private String creatByUsrid;
         private Timestamp updtTs;
         private String updtByUsrid;
         private Set<RfuiRfLgcMap> rfuiRfLgcMaps = new HashSet<RfuiRfLgcMap>(0);

         // Constructors

         /** default constructor */
         public RfuiRfDef() {
         }

         // Property accessors
         @Id
         @SequenceGenerator(name="ID_GENERATOR", sequenceName="DEF_SEQ")
         @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="DEFID_GENERATOR")
         @Column(name = "RF_ID", unique = true, nullable = false, precision = 22, scale = 0)
         public BigDecimal getRfId() {
              return this.rfId;
         }

         public void setRfId(BigDecimal rfId) {
              this.rfId = rfId;
         }

         @Column(name = "RF_CD", length = 40)
         public String getRfCd() {
              return this.rfCd;
         }

         public void setRfCd(String rfCd) {
              this.rfCd = rfCd;
         }

         @Column(name = "MODIFIED_FLG", length = 1)
         public String getModifiedFlg() {
              return this.modifiedFlg;
         }

         public void setModifiedFlg(String modifiedFlg) {
              this.modifiedFlg = modifiedFlg;
         }

         @Column(name = "CREAT_TS", length = 11)
         public Timestamp getCreatTs() {
              return this.creatTs;
         }

         public void setCreatTs(Timestamp creatTs) {
              this.creatTs = creatTs;
         }

         @Column(name = "CREAT_BY_USRID", length = 10)
         public String getCreatByUsrid() {
              return this.creatByUsrid;
         }

         public void setCreatByUsrid(String creatByUsrid) {
              this.creatByUsrid = creatByUsrid;
         }

         @Column(name = "UPDT_TS", length = 11)
         public Timestamp getUpdtTs() {
              return this.updtTs;
         }

         public void setUpdtTs(Timestamp updtTs) {
              this.updtTs = updtTs;
         }

         @Column(name = "UPDT_BY_USRID", length = 10)
         public String getUpdtByUsrid() {
              return this.updtByUsrid;
         }

         public void setUpdtByUsrid(String updtByUsrid) {
              this.updtByUsrid = updtByUsrid;
         }

         @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "rfuiRfDef")
         public Set<RfuiRfLgcMap> getRfuiRfLgcMaps() {
              return this.rfuiRfLgcMaps;
         }

         public void setRfuiRfLgcMaps(Set<RfuiRfLgcMap> rfuiRfLgcMaps) {
              this.rfuiRfLgcMaps = rfuiRfLgcMaps;
         }

    }
  • 4. Re: When Parent is saved, Child doesnt get saved.
    gimbal2 Guru
    Currently Being Moderated
    Jebus, a BigDecimal ID column. You must be planning to store the entire universe in there. I've never managed to go over a precision 10 sequence generated primary key myself...

    Same difference: its backwards. You have a Map with one RfuiRfDef child and an RfuiRfDef child belonging to many maps. Huh?

    In this scenario I see only one real way of persisting it.

    - persist RfuiRfDef child object to make it a managed JPA entity
    - assign MANAGED RfuiRfDef child entity to RfuiRfLgcMap object
    - persist RfuiRfLgcMap object to make it a managed JPA entity
    - for completeness, stick the now managed RfuiRfLgcMap parent entity in the rfuiRfLgcMaps set of the child object

    Translate that to regular SQL statements; you can't persist the Map object when you don't first have a RfuiRfDef record so you can store a foreign key relation to it.

    I see an ALL cascade slapped onto everything (that is not good practice, don't use generated code as it is, you have to understand what it all does and adjust according to what is safe and necessary) - perhaps it will work if you in fact persist the RfuiRfDef object like this:

    - create RfuiRfDef child object
    - create RfuiRfLgcMap object (with the RfuiRfDef object set)
    - stick RfuiRfLgcMap object into the RfuiRfDef.rfuiRfLgcMaps set
    - persist RfuiRfDef child object

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points