1 Reply Latest reply: Mar 27, 2012 7:59 AM by JamesSutherland RSS

    Issue with cascade persist using JPA

    926181
      Hello all,
      I have two tables A and B as shown in the following code:

      CREATE TABLE A (
      idA INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
      name VARCHAR(30) NOT NULL,
      PRIMARY KEY(idA)
      +);+

      CREATE TABLE B (
      idB VARCHAR(20) NOT NULL,
      A_idA INTEGER UNSIGNED NOT NULL,
      name VARCHAR(30) NOT NULL,
      PRIMARY KEY(idB, A_idA),
      FOREIGN KEY(A_idA)
      REFERENCES A(idA)
      ON DELETE NO ACTION
      ON UPDATE NO ACTION
      +);+



      I created two entities :
      A.java :
      +public class A implements Serializable {+
      private static final long serialVersionUID = 1L;
      +@Id+
      +@GeneratedValue(strategy = GenerationType.IDENTITY)+
      +@Basic(optional = false)+
      +@Column(name = "IDA", nullable = false)+
      private Integer ida;
      +@Basic(optional = false)+
      +@Column(name = "NAME", nullable = false, length = 30)+
      private String name;
      +@OneToMany(cascade = CascadeType.ALL, mappedBy = "a")+
      private List<B> bList;
      //getters setters
      +}+

      BPK.java:

      +@Embeddable+
      +public class BPK implements Serializable {+
      +@Basic(optional = false)+
      +@Column(name = "IDB", nullable = false, length = 20)+
      private String idb;
      +@Basic(optional = false)+
      +@Column(name = "A_IDA", nullable = false)+
      private int aIda;

      +public BPK() {+
      +}+

      +public BPK(String idb, int aIda) {+
      this.idb = idb;
      this.aIda = aIda;
      +}+
      //getters setters
      +}+


      B.java:
      +public class B implements Serializable {+
      private static final long serialVersionUID = 1L;
      +@EmbeddedId+
      protected BPK bPK;
      +@Basic(optional = false)+
      +@Column(name = "NAME", nullable = false, length = 30)+
      private String name;
      +@JoinColumn(name = "A_IDA", referencedColumnName = "IDA", nullable = false, insertable = false, updatable = false)+
      +@ManyToOne(optional = false)+
      private A a;
      //getters setters
      +}+




      when I try to insert new rows:


      EntityManagerFactory emf=Persistence.createEntityManagerFactory("threadPU");
      EntityManager em=emf.createEntityManager();


      A a=new A(null,"name1");

      java.util.List<B> lB=new ArrayList<B>();

      BPK bpk1 =new BPK();
      bpk1.setIdb("idB1");
      BPK bpk2 =new BPK();
      bpk1.setIdb("idB2");
      BPK bpk3 =new BPK();
      bpk1.setIdb("idB3");

      B b1=new B(bpk1,"name1");
      B b2=new B(bpk2,"name2");
      B b3=new B(bpk3,"name3");

      b1.setA(a);
      b2.setA(a);
      b3.setA(a);

      lB.add(b1);
      lB.add(b2);
      lB.add(b3);

      a.setBList(lB);


      em.getTransaction().begin();
      em.persist(a);
      em.getTransaction().commit();

      I get this error:
      [EL Warning]: 2012-03-25 14:05:33.43--UnitOfWork(1146586674)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
      Internal Exception: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "CONSTRAINT_42_1: PUBLIC.B FOREIGN KEY(A_IDA) REFERENCES PUBLIC.A(IDA)"; SQL statement:
      INSERT INTO ABCD.PUBLIC.B (NAME, IDB, A_IDA) VALUES (?, ?, ?) [23506-164]
      Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
      Internal Exception: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "CONSTRAINT_42_1: PUBLIC.B FOREIGN KEY(A_IDA) REFERENCES PUBLIC.A(IDA)"; SQL statement:
      INSERT INTO ABCD.PUBLIC.B (NAME, IDB, A_IDA) VALUES (?, ?, ?) [23506-164]
           at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
           at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
           at org.h2.message.DbException.get(DbException.java:169)
           at org.h2.message.DbException.get(DbException.java:169)
           at org.h2.message.DbException.get(DbException.java:146)
           at org.h2.message.DbException.get(DbException.java:146)
           at org.h2.constraint.ConstraintReferential.checkRowOwnTable(ConstraintReferential.java:345)
           at org.h2.constraint.ConstraintReferential.checkRowOwnTable(ConstraintReferential.java:345)
           at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:287)
           at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:287)
           at org.h2.table.Table.fireConstraints(Table.java:862)
           at org.h2.table.Table.fireConstraints(Table.java:862)
           at org.h2.table.Table.fireAfterRow(Table.java:879)
           at org.h2.table.Table.fireAfterRow(Table.java:879)
           at org.h2.command.dml.Insert.insertRows(Insert.java:126)
           at org.h2.command.dml.Insert.update(Insert.java:84)
           at org.h2.command.dml.Insert.insertRows(Insert.java:126)
           at org.h2.command.CommandContainer.update(CommandContainer.java:73)
           at org.h2.command.dml.Insert.update(Insert.java:84)
           at org.h2.command.Command.executeUpdate(Command.java:226)
           at org.h2.command.CommandContainer.update(CommandContainer.java:73)
           at org.h2.server.TcpServerThread.process(TcpServerThread.java:325)
           at org.h2.command.Command.executeUpdate(Command.java:226)
           at org.h2.server.TcpServerThread.run(TcpServerThread.java:146)
           at org.h2.server.TcpServerThread.process(TcpServerThread.java:325)
           at java.lang.Thread.run(Unknown Source)

      Error Code: 23506
      Call: INSERT INTO ABCD.PUBLIC.B (NAME, IDB, A_IDA) VALUES (?, ?, ?)
           bind => [3 parameters bound]
           at org.h2.server.TcpServerThread.run(TcpServerThread.java:146)
      Query: InsertObjectQuery(thread.B[ bPK=thread.BPK[ idb=idB3, aIda=0 ] ])
           at java.lang.Thread.run(Unknown Source)

      Error Code: 23506
      Call: INSERT INTO ABCD.PUBLIC.B (NAME, IDB, A_IDA) VALUES (?, ?, ?)
           bind => [3 parameters bound]
      Query: InsertObjectQuery(thread.B[ bPK=thread.BPK[ idb=idB3, aIda=0 ] ])
           at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
           at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
           at thread.AJpaController.cascade(AJpaController.java:42)
           at thread.tache2.main(tache2.java:49)
      Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
      Internal Exception: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "CONSTRAINT_42_1: PUBLIC.B FOREIGN KEY(A_IDA) REFERENCES PUBLIC.A(IDA)"; SQL statement:
      INSERT INTO ABCD.PUBLIC.B (NAME, IDB, A_IDA) VALUES (?, ?, ?) [23506-164]
           at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
           at org.h2.message.DbException.get(DbException.java:169)
           at org.h2.message.DbException.get(DbException.java:146)
           at org.h2.constraint.ConstraintReferential.checkRowOwnTable(ConstraintReferential.java:345)
           at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:287)
           at org.h2.table.Table.fireConstraints(Table.java:862)
           at org.h2.table.Table.fireAfterRow(Table.java:879)
           at org.h2.command.dml.Insert.insertRows(Insert.java:126)
           at org.h2.command.dml.Insert.update(Insert.java:84)
           at org.h2.command.CommandContainer.update(CommandContainer.java:73)
           at org.h2.command.Command.executeUpdate(Command.java:226)
           at org.h2.server.TcpServerThread.process(TcpServerThread.java:325)
           at org.h2.server.TcpServerThread.run(TcpServerThread.java:146)
           at java.lang.Thread.run(Unknown Source)

      Error Code: 23506
      Call: INSERT INTO ABCD.PUBLIC.B (NAME, IDB, A_IDA) VALUES (?, ?, ?)
           bind => [3 parameters bound]
      Query: InsertObjectQuery(thread.B[ bPK=thread.BPK[ idb=idB3, aIda=0 ] ])
           at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324)
           at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:840)
           at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:906)
           at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:592)
           at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:535)
           at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1702)
           at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:253)
           at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:207)
           at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:193)
           at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:342)
           at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:162)
           at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:177)
           at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:472)
           at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
           at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
           at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:287)
           at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
           at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:829)
           at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:728)
           at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
           at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
           at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2863)
           at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1501)
           at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1483)
           at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1443)
           at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:224)
           at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:191)
           at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:136)
           at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3784)
           at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1407)
           at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:634)
           at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1497)
           at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:265)
           at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1135)
           at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
           ... 3 more
      Caused by: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "CONSTRAINT_42_1: PUBLIC.B FOREIGN KEY(A_IDA) REFERENCES PUBLIC.A(IDA)"; SQL statement:
      INSERT INTO ABCD.PUBLIC.B (NAME, IDB, A_IDA) VALUES (?, ?, ?) [23506-164]
           at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
           at org.h2.message.DbException.get(DbException.java:169)
           at org.h2.message.DbException.get(DbException.java:146)
           at org.h2.constraint.ConstraintReferential.checkRowOwnTable(ConstraintReferential.java:345)
           at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:287)
           at org.h2.table.Table.fireConstraints(Table.java:862)
           at org.h2.table.Table.fireAfterRow(Table.java:879)
           at org.h2.command.dml.Insert.insertRows(Insert.java:126)
           at org.h2.command.dml.Insert.update(Insert.java:84)
           at org.h2.command.CommandContainer.update(CommandContainer.java:73)
           at org.h2.command.Command.executeUpdate(Command.java:226)
           at org.h2.server.TcpServerThread.process(TcpServerThread.java:325)
           at org.h2.server.TcpServerThread.run(TcpServerThread.java:146)
           at java.lang.Thread.run(Unknown Source)

           at org.h2.engine.SessionRemote.done(SessionRemote.java:565)
           at org.h2.command.CommandRemote.executeUpdate(CommandRemote.java:183)
           at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:143)
           at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:129)
           at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:831)
           ... 36 more
      Java Result: 1
        • 1. Re: Issue with cascade persist using JPA
          JamesSutherland
          The issue is your A_IDA is null, because it is mapped by your BPK, and you never set it, so it is null.

          You need to set the value. This will be difficult because your are using an IDENTITY generated value, and the value is not available until after the insert. You could persist the A by itself, then call flush(), then use its id in B. Or you could use TABLE sequencing instead, then the value would be available after persist.

          But, probably better you should get rid of the EmbeddedId, and instead use a IdClass, and mark the ManyToOne as @Id.

          See,
          http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#JPA_2.0

          You could also mark the aIda as insertable = false, updatable = false, instead of the ManyToOne.