2011-12-01 4 views
5

Estoy tratando de implementar la persistencia de algunos objetos Java a través de la asignación de Hibernate en una tabla MySQL. Cuando me comprometo, recibo un mensaje que dice 'La actualización por lotes ha devuelto el conteo de filas inesperadas de la actualización [0]; recuento de filas real: 0; esperado: 1 '.LARGO como clave principal en la asignación de Hibernate a MySQL

Mi hipótesis es que el problema se debe a que tengo un campo long en mi POJO de Java que quiero usar como mi clave principal en la tabla MySQL. Como no pude usar el tipo de datos LONG como mi clave principal en la tabla MySQL (ERROR 1170: columna BLOB/TEXT 'id' utilizada en la especificación de la clave sin una longitud de clave) concluí de google y este post que BIGINT sería el adecuado mapeo para long. Sin embargo, no está actualizando.

Mi prueba POJO Person es muy simple. Tiene 3 campos: id (largo), primer nombre (String), apellido (String) con setters y getters, etc.

Hago el mapeo de hibernación en xml (persona.hbm.xml) que esencialmente se parece a (menos rúbricas):

<hibernate-mapping> 
    <class name="hibernatetest.Person" table="hibernatetest"> 
    <id name="id" type="long" column="id" > 
    <generator class="native"/> 
    </id> 

    <property name="firstname"> 
    <column name="firstname" /> 
    </property> 
    <property name="lastname"> 
    <column name="lastname"/> 
    </property> 
</class> 
</hibernate-mapping> 

Mi java real fragmento de código que se supone que guardar o actualizar el registro es simple:

Transaction tr = session.beginTransaction();    
Person person = new Person(1,"John","Doe"); 
session.saveOrUpdate(person); 
tr.commit(); 

Y aquí está esa cosa, todo esto funciona bien si cambio el tipo de id a un int (Integer) en el objeto Person y en la tabla MySQL. Sin embargo, no tengo esa opción para los objetos reales que deseo persistir, así que la pregunta es; ¿Qué estoy haciendo mal o qué debo hacer para que funcione? Gracias.

SUMAR StackTrace:

Hibernate: update hibernatetest set firstname=?, lastname=? where id=? 
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:81) 
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73) 
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:57) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3006) 
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2908) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3237) 
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:113) 
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:273) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:265) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:187) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) 
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1082) 
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:317) 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175) 
    at com.hibernate.test.TestMain.main(TestMain.java:38) 
nested transactions not supported 

ACTUALIZACIÓN: bien, por fin he trabajado a cabo. Cambié la clase de generador de hibernación de 'nativo' a 'asignado' y ahora funciona como se esperaba. Así que ahora la asignación de hibernación se parece a:

<hibernate-mapping> 
    <class name="hibernatetest.Person" table="hibernatetest"> 
    <id name="id" type="long" column="id" > 
    <generator class="assigned"/> 
    </id> 

    <property name="firstname"> 
    <column name="firstname" /> 
    </property> 
    <property name="lastname"> 
    <column name="lastname"/> 
    </property> 
</class> 
</hibernate-mapping> 

que admitir que no sabía el significado de ese parámetro (copiado de algún sitio) y no tenía idea que podría causar este gran dolor de cabeza. Encontré esto explanation que fue bastante útil.

Aparentemente no tengo suficientes credenciales para responder mis propias preguntas, así que supongo que permanecerá abierto o si alguien proporciona una respuesta vacía, la aceptaré. Gracias.

+0

puede publicar su stacktrace completo, largo y BIGINT debería funcionar bien, lo he utilizado personalmente no se han encontrado problemas, por favor comparta su stacktrace – mprabhat

+0

¿Cuál es la definición de tipo de columna db? ¿Y tu tipo de atributo de id? De todos modos, Bigint para columna, y Long para java atributo está bien. – polypiel

+0

@mprabhat Hecho. Tiene un mensaje que dice 'transacciones anidadas no compatibles' que no vi antes. No sé lo que significa, sin embargo? – hgus1294

Respuesta

5

Cuando se utiliza el método de saveOrUpdate()hibernación dispara la consulta de inserción Si el ID del objeto es null y update si se trata de cualquier otro valor. Puedo ver el código, Person person = new Person(1,"John","Doe"); estableciendo id en 1 y llamando al método saveOrUpdate(). Supongo que no hay entradas para la ID 1 y, por lo tanto, se emite el error.

Para que funcione, debe realizar los cambios a continuación.

  1. cambiar el tipo de id en persona a Long de long (La clase de contenedor para que pueda apoyar nulo).

  2. Escriba el constructor new Person("John","Doe"); y guarde ese objeto.

No es una buena idea para mantener el <generator class="assigned"/> de los datos transaccionales. En su lugar, debe seguir el native como lo estaba intentando primero.

Creo que esta es una manera más limpia de resolver su problema inicial, aunque haya encontrado una solución alternativa.

+0

Gracias. Tiene razón al suponer que no había ningún registro previo con 'id' = 1 antes de' SaveOrUpdate'. Traté de cambiar el tipo de clase a 'Largo' de acuerdo con su sugerencia, pero vuelve al mismo error si configuro el generador como' nativo'. No entendí tu segundo punto donde omites 'id' del constructor. El 'id' no es una identificación autogenerada, así que necesito poder establecerlo en un valor específico. – hgus1294

+0

Quiero decir que deje que su base de datos elija la identificación y no codifique el ID al estado mientras se guarda. Elija entre las opciones [aquí] (http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id) sobre cómo puede hacerlo. – ManuPK

+0

OK, lo tengo. En mi situación actual, los 'id' se proporcionan desde un servicio externo y deben persistir como tales, por lo que no puedo dejar que db decida. Si solo cambio el tipo de clase a 'Largo' y conservo un constructor que toma' Largo', obtengo la excepción original. ¿Es eso como se esperaba o no entendí otra cosa? Mencionó un riesgo con generator = 'assigned' para transacciones. ¿Cual es el riesgo? – hgus1294

Cuestiones relacionadas