Saltar al contenido

¿Cómo reiniciar los generadores de secuencias de Hibernate?

Solución:

Quizás una de las soluciones sea ejecutar cada prueba JUNIT en una nueva sessionfactory. así que abra y cierre la fábrica de sesiones usando @Before y @After

Pros

  • obtienes generadores de secuencia desde el principio

Contras

  • Se necesitan unos segundos más para todos los casos de prueba de JUNIT

Actualizar

Según el comentario, otra forma es restablecer la secuencia en cada prueba JUNIT en el método @Before

ALTER SEQUENCE Test.sequence RESTART WITH 1

Estaba enfrentando el mismo problema y no encontré una forma integrada de hacerlo. Estamos usando hibernate 4.2.7.

Después de depurar profundamente en hibernación, terminé extendiendo el generador de secuencias. Creamos entidades usando el generador de secuencia estándar:

@SequenceGenerator(name = "SomeSeq", sequenceName = "DB_SEQ", allocationSize = 50)

Hibernate crea un org.hibernate.id.SequenceHiLoGenerator para cada entidad. SequnceHiLoGenerator delega en una instancia de OptimizerFactory.LegacyHiLoAlgorithmOptimizer.

Para restablecer los contadores de secuencia y forzar la sincronización con la secuencia de la base de datos, debe restablecer las variables internas en LegacyHiLoAlgorithmOptimizer. Desafortunadamente, estas variables son privadas y no se pueden modificar. Traté de encontrar una manera de usar la herencia, pero no encontré una solución elegante. Finalmente yo
creó una copia de origen del SequenceHiLoGenerator y la extendió con una función de reinicio simple:

public class ResetableIdGenerator extends SequenceGenerator {
               public static int cycle = 0; // global, indicating current test cycle
               protected int startingCycle = 0; // instance, indicating the test cycle the LegacyHiLoAlgorithmOptimizer was used the last time
    [...]
        public synchronized Serializable generate(final SessionImplementor session, Object obj) {
            // create a new HiLoOptimizer if there's a new test cycle
            if (startingCycle < cycle) {
                hiloOptimizer = new OptimizerFactory.LegacyHiLoAlgorithmOptimizer(getIdentifierType().getReturnedClass(),
                        maxLo);
                startingCycle = cycle;
            }
[....]

Modifique las entidades para usar el generador personalizado:

@GenericGenerator(name = "SomeSeq", strategy = "yourpackage.ResetableIdGenerator", parameters = {
        @Parameter(name = "sequence", value = "DB_SEQ"), @Parameter(name = "max_lo", value = "49") })

Restablezca el generador de secuencia entre su prueba (@antes o @después):

// reset Hibernate Sequences
ResetableIdGenerator.cycle++;

Sé que esta no es una buena solución, es un truco. Pero funciona y tal vez ayude a encontrar una mejor solución.

EDITAR 20170504: Mi publicación inicial contenía un error: los parámetros “nombre de secuencia” y “tamaño de asignación” son parámetros de JPA. El GenericGenerator es de hibernate. En lugar de “sequenceName” tienes que usar “sequence”, en lugar de “allocationSize” tienes que usar “max_lo” y configurarlo en assignSize-1. Actualicé el ejemplo de código. ¡Perdón!

Hoy me enfrenté al mismo problema. Como no pude encontrar otra solución, intenté tomar la solución de OleG. Lamentablemente mientras tanto org.hibernate.id.SequenceGenerator está marcado como obsoleto. Por lo tanto, utilicé el org.hibernate.id.enhanced.SequenceStyleGenerator. Si alguien más lo necesita, aquí está mi solución personalizada:

public class ResettableSequenceStyleGenerator extends SequenceStyleGenerator {

    private static int cycle = 0;
    private int instanceCycle = cycle;

    private Type configure_type = null;
    private Properties configure_params = null;
    private ServiceRegistry configure_serviceRegistry = null;

    private Database registerExportables_database = null;

    @Override
    public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {

        configure_type = type;
        configure_params = params;
        configure_serviceRegistry = serviceRegistry;

        super.configure(type, params, serviceRegistry);
    }

    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {

        if (instanceCycle != cycle) {
            super.configure(configure_type, configure_params, configure_serviceRegistry);
            super.registerExportables(registerExportables_database);
            instanceCycle = cycle;
        }

        return super.generate(session, object);
    }

    @Override
    public void registerExportables(Database database) {

        registerExportables_database = database;

        super.registerExportables(database);
    }

    public static void resetAllInstances() {
        cycle++;
    }
}

Selecciona el ResettableSequenceStyleGenerator como estrategia en el GenericGenerator anotación como se describe en el artículo de OleG:

@GenericGenerator(name = "SomeSeq", strategy = "yourpackage.ResettableSequenceStyleGenerator", parameters = ...)

En mi clase IntegrationTest, luego restablezco las secuencias antes de cada método de prueba:

@Before
public void resetSequences() {
    ResettableSequenceStyleGenerator.resetAllInstances();
}
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *