-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Could not execute JDBC batch update - with composity key
PostPosted: Wed Dec 02, 2009 8:33 am 
Newbie

Joined: Wed Dec 02, 2009 7:57 am
Posts: 2
Hello.
I have three entities called (spanish) Macroproceso, Proceso and TipoEntregable. Macroproceso has many Proceso and Proceso has many TipoEntregable. All the keys are natural keys:
  • Macroproceso has "codigo".
  • Proceso has "codigo" and "codigo_macroproceso" because codigo is not unique. "codigo_macroproceso" is also FK to Macroproceso.
  • TipoEntregable has "codigo", "codigo_proceso" and "codigo_macroproceso" because codigo is not unique. "codigo_macroproceso" and "codigo_proceso" are also FK to Proceso.

The problem is when I try to perform an insert (save() method) and then I do the commit(). I know natural keys and composites keys like theese are not recommended, but I need to do it this mazy way...

Please, could anyone tell me where is the mistake? I'll know paste all the information.

Ah, why I see questions marks instead of the inserted values in the log? is there a way to see the values? (i refer to: insert into TIPOS_ENTREGABLE (NOMBRE, CODIGO, CODIGO_MACROPROCESO, CODIGO_PROCESO) values (?, ?, ?, ?)).

Here are the POJOs for the persistente entities:

Code:
public class Macroproceso {
   
   private String codigo; // PK (natural, app assigned, single)
   private String descripcion;
   private Set<Proceso> procesos; // ONE-TO-MANY PROCESOS
...
}

public class Proceso {
   
   private ProcesoId id; // PK (natural, app assigned, composite)
   private String descripcion;
   private Set<TipoEntregable> tiposDeEntregable; // ONE-TO-MANY TIPOS_ENTREGABLES
...
}

public class TipoEntregable {
   
   private TipoEntregableId id;    // PK (natural, app assigned, composite)
   private String nombre;
...
}


And here, you can see the classes for the composites ids:
Code:
public class ProcesoId implements Serializable {
   private String codigoProceso;
   private Macroproceso macroproceso; // FK MANY-TO-ONE MACROPROCESOS
...
}

public class TipoEntregableId implements Serializable {

   private String codigoTipoEntregable;
   private Proceso proceso; // FK MANY-TO-ONE PROCESOS
...
}


And here are the mappings (just the class elements of the three xml sources):

Code:

for macroprocesos:
    <class name="Macroproceso" table="MACROPROCESOS">
   
      <id name="codigo" column="CODIGO" length="3">
         <generator class="assigned"/>
      </id>
      
        <property name="descripcion" column="DESCRIPCION" />
       
      <set name="procesos" table="PROCESOS">
         <key>
            <column name="CODIGO_MACROPROCESO" />            
         </key>
         <one-to-many class="Proceso" />
      </set>

    </class>


for procesos:

    <class name="Proceso" table="PROCESOS">
   
       <composite-id name="id" class="ProcesoId">
           <key-property name="codigoProceso" column="CODIGO"/>
           <key-many-to-one name="macroproceso" column="CODIGO_MACROPROCESO" class="Macroproceso"/>
       </composite-id>
   
       <property name="descripcion" column="DESCRIPCION" />
       
       <set name="tiposDeEntregable" inverse="true">
         <key>
            <column name="CODIGO_PROCESO"/>
            <column name="CODIGO_MACROPROCESO"/>
         </key>
         <one-to-many class="TipoEntregable"/>
      </set>
   
   
    </class>

for tipos entregable:

<class name="TipoEntregable" table="TIPOS_ENTREGABLE">
   
        <composite-id name="id" class="TipoEntregableId">
           <key-property name="codigoTipoEntregable" column="CODIGO"/>
           <key-many-to-one name="proceso" class="Proceso">
              <column name="CODIGO_MACROPROCESO" />
              <column name="CODIGO_PROCESO" />
           </key-many-to-one>
       </composite-id>   
       
        <property name="nombre" column="NOMBRE" />

    </class>




And here is the log:

Code:
12:54:10,981 DEBUG SessionImpl:84 - opened session at timestamp: 12597548509
12:54:10,981 DEBUG JDBCTransaction:84 - begin
12:54:10,981 DEBUG ConnectionManager:84 - opening JDBC connection
12:54:10,981 DEBUG JDBCTransaction:84 - current autocommit status: false
12:54:13,809 DEBUG AbstractSaveEventListener:84 - generated identifier: component[codigoTipoEntregable,proceso]{proceso=com.endesa.mproweb.crscrscrs.negocio.entidad.Proceso#component[codigoProceso,macroproceso]{macroproceso=com.endesa.mproweb.crscrscrs.negocio.entidad.Macroproceso#DIM, codigoProceso=DIS}, codigoTipoEntregable=210}, using strategy: org.hibernate.id.Assigned
12:54:15,731 DEBUG JDBCTransaction:84 - commit
12:54:15,731 DEBUG AbstractFlushingEventListener:84 - processing flush-time cascades
12:54:15,731 DEBUG AbstractFlushingEventListener:84 - dirty checking collections
12:54:15,731 DEBUG AbstractFlushingEventListener:84 - Flushed: 1 insertions, 0 updates, 0 deletions to 1 objects
12:54:15,731 DEBUG AbstractFlushingEventListener:84 - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
12:54:15,731 DEBUG Printer:84 - listing entities:
12:54:15,762 DEBUG Printer:84 - com.endesa.mproweb.crscrscrs.negocio.entidad.TipoEntregable{nombre=Diseño Funcional y de Usuario, id=component[codigoTipoEntregable,proceso]{proceso=com.endesa.mproweb.crscrscrs.negocio.entidad.Proceso#component[codigoProceso,macroproceso]{macroproceso=com.endesa.mproweb.crscrscrs.negocio.entidad.Macroproceso#DIM, codigoProceso=DIS}, codigoTipoEntregable=210}}
12:54:15,762 DEBUG AbstractBatcher:84 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
12:54:15,762 DEBUG SQL:84 - insert into TIPOS_ENTREGABLE (NOMBRE, CODIGO, CODIGO_MACROPROCESO, CODIGO_PROCESO) values (?, ?, ?, ?)
Hibernate: insert into TIPOS_ENTREGABLE (NOMBRE, CODIGO, CODIGO_MACROPROCESO, CODIGO_PROCESO) values (?, ?, ?, ?)
12:54:15,778 DEBUG AbstractBatcher:84 - Executing batch size: 1
12:54:15,778 DEBUG AbstractBatcher:84 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
12:54:15,794 DEBUG JDBCExceptionReporter:89 - Could not execute JDBC batch update [insert into TIPOS_ENTREGABLE (NOMBRE, CODIGO, CODIGO_MACROPROCESO, CODIGO_PROCESO) values (?, ?, ?, ?)]
java.sql.BatchUpdateException: failed batch
   at org.hsqldb.jdbc.jdbcStatement.executeBatch(Unknown Source)
   at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(Unknown Source)
   at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
   at com.endesa.mproweb.test.TestMain.createAndStoreTipoEntregable(TestMain.java:127)
   at com.endesa.mproweb.test.TestMain.main(TestMain.java:33)
12:54:15,794  WARN JDBCExceptionReporter:104 - SQL Error: 0, SQLState: null
12:54:15,794 ERROR JDBCExceptionReporter:114 - failed batch
12:54:15,794 ERROR AbstractFlushingEventListener:119 - Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
   at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
   at com.endesa.mproweb.test.TestMain.createAndStoreTipoEntregable(TestMain.java:127)
   at com.endesa.mproweb.test.TestMain.main(TestMain.java:33)
Caused by: java.sql.BatchUpdateException: failed batch
   at org.hsqldb.jdbc.jdbcStatement.executeBatch(Unknown Source)
   at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(Unknown Source)
   at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
   ... 9 more


Thank you very much,
Pepe Martínez


Top
 Profile  
 
 Post subject: Re: Could not execute JDBC batch update - with composity key
PostPosted: Wed Dec 02, 2009 11:28 am 
Newbie

Joined: Wed Dec 02, 2009 7:57 am
Posts: 2
Hello.

I have just found the problem (and the solution). I'll tell you beacause it maybe can help someone.

First of all, I'll include the "cliente code", because I forgot it in the previouse post:

Code:
// Insert TipoEntregable "210" belonging to Proceso "DIS" of Macroproceso "DIM".

// Macroproceso
Macroproceso m=new Macroproceso();
m.setCodigo("DIM"); // DIM is Macroproceso PK

// Proceso PK
ProcesoId pid=new ProcesoId("DIS",m);

// TipoEntregable PK
Proceso p=new Proceso();
p.setId(pid);
TipoEntregableId tid=new TipoEntregableId("210",p);

// TipoEntregable to insert
TipoEntregable t=new TipoEntregable();
t.setId(tid); // Set the PK
t.setNombre("Nombre del 210"); // Set additional info

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();

session.save(t);
session.getTransaction().commit(); // Exception throwed here.


Now, THE PROBLEM:

Debugging with eclipse, i have set up a java exception breakpoint for BatchUpdateException. I have watched the 'this' variable, which is a jdbcPreparedStatement:

org.hsqldb.jdbc.jdbcPreparedStatement@666d83[sql=[insert into TIPOS_ENTREGABLE (NOMBRE, CODIGO, CODIGO_MACROPROCESO, CODIGO_PROCESO) values (?, ?, ?, ?)], parameters=[[Nombre del 210], [210], [DIS], [DIM]]]

That's to say, the assignation is:
- NOMBRE: Diseño Funcional y de Usuario
- CODIGO: 210
- CODIGO_MACROPROCESO: DIS
- CODIGO_PROCESO: DIM

But 'DIS' should be assigned to 'CODIGO_PROCESO' and 'DIM' to 'CODIGO_MACROPROCESO'. The exception was thrown beacuse a integrity rule was being violated (DIS is not a Macroproceso and DIM is not a Proceso).

THE SOLUTION:

In the mapping for the TipoEntregable entity, the key-many-to-one was:
Code:
           <key-many-to-one name="proceso" class="Proceso">              
              <column name="CODIGO_MACROPROCESO" />
              <column name="CODIGO_PROCESO" />
           </key-many-to-one>


But the composite-id of the Proceso entity was:
Code:
<composite-id name="id" class="ProcesoId">
           <key-property name="codigoProceso" column="CODIGO"/>
           <key-many-to-one name="macroproceso" column="CODIGO_MACROPROCESO" class="Macroproceso"/>
</composite-id>


And, as the documentation says, the order of the columns in the FK declaration must be the same as the order of the columnas of the PK declaration. So, changing the mapping for the entity TipoEntregable like this:
Code:
           <key-many-to-one name="proceso" class="Proceso">              
              <column name="CODIGO_PROCESO" />
              <column name="CODIGO_MACROPROCESO" />
           </key-many-to-one>


The insertion works perfectly because it associate correctly the values of the Proceso with the FK columns of the TipoEntregable table in the database.

Regards,
Pepe Martínez


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.