example conectar con hibernate postgresql insert database-partitioning

conectar - hibernate insertar lote con postgresql particionado



hibernate sequence postgresql (5)

¿Hay alguna solución para la inserción de lotes a través de la hibernación en la tabla postgresql particionada? Actualmente recibo un error como este ...

ERROR org.hibernate.jdbc.AbstractBatcher - Exception executing batch: 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:61) at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46) at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:68)....

he encontrado este enlace http://lists.jboss.org/pipermail/hibernate-dev/2007-October/002771.html pero no puedo encontrar ningún sitio en la web donde se resuelva este problema o cómo se puede solucionar


Aparece si puede usar REGLAS en lugar de desencadenantes para la inserción, entonces puede devolver el número correcto, pero solo con una sola REGLA sin una instrucción WHERE.

ref1

ref2

ref3

Otra opción puede ser crear una vista que "envuelva" la tabla particionada, luego devuelva la fila NUEVA para indicar una actualización correcta de la fila, sin agregar accidentalmente una fila extra no deseada a la tabla maestra.

create view tablename_view as select * from tablename; -- create trivial wrapping view CREATE OR REPLACE FUNCTION partitioned_insert_trigger() -- partitioned insert trigger RETURNS TRIGGER AS $$ BEGIN IF (NEW.partition_key>= 5500000000 AND NEW.partition_key < 6000000000) THEN INSERT INTO tablename_55_59 VALUES (NEW.*); ELSIF (NEW.partition_key >= 5000000000 AND NEW.partition_key < 5500000000) THEN INSERT INTO tablename_50_54 VALUES (NEW.*); ELSIF (NEW.partition_key >= 500000000 AND NEW.partition_key < 1000000000) THEN INSERT INTO tablename_5_9 VALUES (NEW.*); ELSIF (NEW.partition_key >= 0 AND NEW.partition_key < 500000000) THEN INSERT INTO tablename_0_4 VALUES (NEW.*); ELSE RAISE EXCEPTION ''partition key is out of range. Fix the trigger function''; END IF; RETURN NEW; -- RETURN NEW in this case, typically you''d return NULL from this trigger, but for views we return NEW END; $$ LANGUAGE plpgsql; CREATE TRIGGER insert_view_trigger INSTEAD OF INSERT ON tablename_view FOR EACH ROW EXECUTE PROCEDURE partitioned_insert_trigger(); -- create "INSTEAD OF" trigger

ref: http://www.postgresql.org/docs/9.2/static/trigger-definition.html

Si fue a la ruta de envoltura de vista una opción es definir también desencadenantes triviales "en lugar de" para eliminar y actualizar, también puede usar el nombre de la tabla de vista en lugar de su tabla normal en todas las transacciones.

Otra opción que utiliza la vista es crear una regla de inserción para que cualquier inserción en la tabla principal vaya a la vista [que usa su desencadenador], ex (suponiendo que ya tiene partitioned_insert_trigger y tablename_view e insert_view_trigger creados como se indica más arriba)

create RULE use_right_inserter_tablename AS ON INSERT TO tablename DO INSTEAD insert into tablename_view VALUES (NEW.*);

Luego usará su nuevo inserto de envoltura de vista de trabajo.



Me enfrenté al mismo problema mientras insertaba documentos a través de Hibernate después de que la búsqueda descubrió que esperaba que se devolvieran las filas actualizadas, así que en lugar de nulo, cámbielo a nuevo en el procedimiento desencadenante, que resolverá el problema como se muestra a continuación.

REGRESAR NUEVO


Puede intentar usar un Batcher personalizado configurando la propiedad hibernate.jdbc.factory_class. Asegurándose de que hibernar no verificará la cuenta de actualización de las operaciones por lotes podría solucionar su problema, puede lograrlo haciendo que su Batcher personalizado amplíe la clase BatchingBatcher, y luego anule el método doExecuteBatch (...) para que se vea así:

@Override protected void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException { if ( batchSize == 0 ) { log.debug( "no batched statements to execute" ); } else { if ( log.isDebugEnabled() ) { log.debug( "Executing batch size: " + batchSize ); } try { // checkRowCounts( ps.executeBatch(), ps ); ps.executeBatch(); } catch (RuntimeException re) { log.error( "Exception executing batch: ", re ); throw re; } finally { batchSize = 0; } } }

Tenga en cuenta que el nuevo método no verifica los resultados de la ejecución de las declaraciones preparadas. Tenga en cuenta que realizar este cambio podría afectar la hibernación de alguna forma inesperada (o tal vez no).


THX! funcionó, sin problemas, hasta ahora:) .... una cosa ... Tuve que implementar la clase BatcherFactory y ponerla en el archivo persistence.xml , así:

property name="hibernate.jdbc.factory_class" value="path.to.my.batcher.factory.implementation"

de esa fábrica llamé a mi implementación de dosificador con el código anterior

ps hibernate core 3.2.6 GA

Gracias una vez más