strategy sequencegenerator generationtype generatedvalue generate example data autoincrement java jpa

sequencegenerator - java hibernate sequence generator example



Java-JPA-Generadores-@SequenceGenerator (4)

Estoy aprendiendo JPA y tengo confusión en la anotación @SequenceGenerator .

Según entiendo, automáticamente asigna un valor a los campos / propiedades de identidad numérica de una entidad.

Q1. ¿Utiliza este generador de secuencias la capacidad de generación de valor numérico creciente de la base de datos o genera el número por sí mismo?

Q2. Si JPA usa la función de incremento automático de la base de datos, ¿funcionará con las áreas de almacenamiento de datos que no tienen la función de incremento automático?

Q3. Si JPA genera valor numérico por sí mismo, ¿cómo sabe la implementación de JPA qué valor generará a continuación? ¿Consulta primero con la base de datos para ver qué valor se almacenó en último lugar para generar el valor (último + 1)?

Q4. Por favor, también arroja algo de luz sobre allocationSize propiedades sequenceName y allocationSize de la anotación @SequenceGenerator .

Aunque esta pregunta es muy antigua y me encontré con ella por mis propios problemas con JPA 2.0 y las secuencias de Oracle.

Quiero compartir mi investigación sobre algunas de las cosas:

Relación entre @SequenceGenerator (allocationSize) de GenerationType.SEQUENCE y INCREMENT BY en la definición de secuencia de la base de datos

Asegúrese de que @SequenceGenerator (allocationSize) tenga el mismo valor que INCREMENT BY en la definición de secuencia de la base de datos para evitar problemas (lo mismo se aplica al valor inicial).

Por ejemplo, si definimos la secuencia en la base de datos con un valor INCREMENT BY de 20, establezca el tamaño de asignación en SequenceGenerator también en 20. En este caso, la JPA no realizará una llamada a la base de datos hasta que alcance la siguiente marca 20 mientras incrementa cada valor por 1 internamente. Esto ahorra llamadas a la base de datos para obtener el siguiente número de secuencia cada vez. El efecto secundario de esto es: cada vez que se vuelve a implementar la aplicación o se reinicia el servidor, llamará a la base de datos para obtener el siguiente lote y verá los saltos en los valores de secuencia. También tenemos que asegurarnos de que la definición de la base de datos y la configuración de la aplicación estén sincronizados, lo que puede no ser posible todo el tiempo, ya que ambos son administrados por diferentes grupos y usted puede perder el control rápidamente. Si el valor de la base de datos es menor que el tamaño de asignación, verá errores de restricción PrimaryKey debido a valores duplicados de Id. Si el valor de la base de datos es mayor que el tamaño de asignación, verá saltos en los valores de Id.

Si la secuencia de la base de datos INCREMENT BY se establece en 1 (que es lo que generalmente hacen los DBA), establezca el allocationSize como también 1 para que estén sincronizados, pero la base de datos de JPA llama para obtener el siguiente número de secuencia cada vez.

Si no desea la llamada a la base de datos cada vez, use la estrategia GenerationType.IDENTITY y tenga el valor @Id establecido por la activación de la base de datos. Con GenerationType.IDENTITY, tan pronto como llamemos a em.persist, el objeto se guarda en DB y se asigna un valor a id al objeto devuelto para que no tengamos que hacer un em.merge o em.flush . (Esto puede ser específico del proveedor de JPA ... No estoy seguro)

Otra cosa importante:

JPA 2.0 ejecuta automáticamente el comando ALTER SEQUENCE para sincronizar el allocationSize y el INCREMENT BY en la secuencia de la base de datos. Como generalmente utilizamos un nombre de esquema diferente (nombre de usuario de la aplicación) en lugar del esquema real donde existe la secuencia y el nombre de usuario de la aplicación no tendrá privilegios de ALTERAR SECUENCIA, es posible que vea la advertencia a continuación en los registros:

000004c1 Runtime W CWWJP9991W: openjpa.Runtime: Warn: no se pueden almacenar en caché los valores de secuencia para la secuencia "RECORD_ID_SEQ". Su aplicación no tiene permiso para ejecutar un comando ALTERAR SECUENCIA. Asegúrese de que tiene el permiso apropiado para ejecutar un comando ALTERAR SECUENCIA.

Como el JPA no podía alterar la secuencia, JPA llama a la base de datos cada vez para obtener el siguiente número de secuencia, independientemente del valor de @ SequenceGenerator.allocationSize. Esta podría ser una consecuencia no deseada de la que debemos ser conscientes.

Para que JPA no ejecute este comando, configure este valor - en persistence.xml. Esto garantiza que JPA no intente ejecutar el comando ALTER SEQUENCE. Sin embargo, escribe una advertencia diferente:

00000094 Runtime W CWWJP9991W: openjpa.Runtime: Warn: la propiedad "openjpa.jdbc.DBDictionary = disableAlterSeqenceIncrementBy" está establecida en verdadero. Esto significa que la sentencia SQL ''ALTER SEQUENCE ... INCREMENT BY'' no se ejecutará para la secuencia "RECORD_ID_SEQ". OpenJPA ejecuta este comando para garantizar que el valor INCREMENT BY de la secuencia definido en la base de datos coincida con el allocationSize que se define en la secuencia de la entidad. Con esta declaración SQL desactivada, es responsabilidad del usuario asegurarse de que la definición de secuencia de la entidad coincida con la secuencia definida en la base de datos.

Como se señala en la advertencia, es importante que nos aseguremos de que @ SequenceGenerator.allocationSize y INCREMENT BY en la definición de la secuencia de la base de datos estén sincronizados, incluido el valor predeterminado de @SequenceGenerator (allocationSize) que es 50. De lo contrario, provocará errores.


Tengo un esquema de MySQL con valores de autogen. Utilizo la etiqueta strategy=GenerationType.IDENTITY y parece funcionar bien en MySQL. Supongo que debería funcionar también la mayoría de los motores de db.

CREATE TABLE user ( id bigint NOT NULL auto_increment, name varchar(64) NOT NULL default '''', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

User.java :

// mark this JavaBean to be JPA scoped class @Entity @Table(name="user") public class User { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private long id; // primary key (autogen surrogate) @Column(name="name") private String name; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name=name; } }


Yo uso esto y funciona bien

@Id @GeneratedValue(generator = "SEC_ODON", strategy = GenerationType.SEQUENCE) @SequenceGenerator(name = "SEC_ODON", sequenceName = "SO.SEC_ODON",allocationSize=1) @Column(name="ID_ODON", unique=true, nullable=false, precision=10, scale=0) public Long getIdOdon() { return this.idOdon; }


sequenceName es el nombre de la secuencia en el DB. Así es como se especifica una secuencia que ya existe en el DB. Si realiza esta ruta, debe especificar el allocationSize que debe tener el mismo valor que la secuencia de DB usa como "incremento automático".

Uso:

@GeneratedValue(generator="my_seq") @SequenceGenerator(name="my_seq",sequenceName="MY_SEQ", allocationSize=1)

Si lo desea, puede dejar que cree una secuencia para usted. Pero para hacer esto, debe usar SchemaGeneration para que se cree. Para hacer esto, usa:

@GeneratedValue(strategy=GenerationType.SEQUENCE)

Además, puede usar la generación automática, que usará una tabla para generar los ID. También debe usar SchemaGeneration en algún momento cuando use esta característica, para que la tabla del generador pueda ser creada. Para hacer esto, usa:

@GeneratedValue(strategy=GenerationType.AUTO)