es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Hay alguna forma de tener identificadores de clave primaria sin que haya brechas?

Estoy creando una aplicación con Java Spring y Oracle DB.

En la aplicación, quiero generar un valor de clave primaria que sea único, ordenado y sin espacios: 1,2,3,4,5 en lugar de 1,2,5,7,8,9.

En un momento dado, he utilizado max(id) + 1 para obtener el valor máximo del id y el id de la siguiente/transacción actual. Sin embargo, sé que no es perfecto en el caso de concurrencia con múltiples usuarios o sesiones.

He intentado utilizar secuencias, pero incluso con la etiqueta ORDER, todavía podría haber brechas con la posibilidad de una transacción fallida.

CREATE SEQUENCE num_seq 
START WITH 1 
INCREMENT BY 1 
ORDER NOCACHE NOCYCLE;

Necesito que haya valores sin brechas como requisito, sin embargo, no estoy seguro de cómo es posible en el caso de múltiples usuarios/múltiples sesiones.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Como experto en TI especializado en SQL, bases de datos, Oracle, clave primaria y secuencial, entiendo el problema que enfrenta al crear un valor de clave primaria sin brechas y ordenado. Para abordar este problema, sugiero utilizar la función SEQUENCE de Oracle con la configuración adecuada.

    En primer lugar, debería utilizar la opción CACHE en lugar de NOCACHE para mejorar el rendimiento, ya que reduce la sobrecarga de las operaciones frecuentes de acceso al disco. En segundo lugar, utilice la opción CYCLE en lugar de NOCYCLE para permitir que la secuencia se reinicie y reutilice valores generados anteriormente en caso de alcanzar el valor máximo.

    Para garantizar valores sin brechas, puede utilizar la opción NOORDER y asignar manualmente el siguiente valor en una transacción. Esto se puede hacer adquiriendo un bloqueo exclusivo en el objeto de secuencia antes de obtener el siguiente valor y luego liberar el bloqueo después de la transacción.

    Aquí hay un ejemplo de código para crear el objeto de secuencia y utilizarlo en Java Spring:

    CREATE SEQUENCE num_seq
    START WITH 1
    INCREMENT BY 1
    CACHE 20
    CYCLE
    NOORDER;
    
    import org.springframework.jdbc.core.JdbcTemplate;
    import javax.sql.DataSource;
    
    public class SequenceGenerator {
        private final JdbcTemplate jdbcTemplate;
    
        public SequenceGenerator(DataSource dataSource) {
            this.jdbcTemplate = new JdbcTemplate(dataSource);
        }
    
        public synchronized int getNextValue() {
            this.jdbcTemplate.execute("LOCK TABLE num_seq IN EXCLUSIVE MODE");
            int nextVal = this.jdbcTemplate.queryForObject("SELECT num_seq.NEXTVAL FROM DUAL", Integer.class);
            this.jdbcTemplate.execute("COMMIT");
            return nextVal;
        }
    }
    

    Luego, puede utilizar esta clase SequenceGenerator para obtener el siguiente valor en su servicio transaccional de la siguiente manera:

    @Service
    @Transactional
    public class MyService {
        private final SequenceGenerator sequenceGenerator;
    
        public MyService(DataSource dataSource) {
            this.sequenceGenerator = new SequenceGenerator(dataSource);
        }
    
        public void createRecord() {
            int primaryKey = this.sequenceGenerator.getNextValue();
            // usar primaryKey en la declaración INSERT
        }
    }
    

    Espero que esta solución le ayude a generar valores de clave primaria sin brechas y ordenados en su aplicación con Oracle DB y Java Spring.

Comments are closed.