Conosciamo tutti il comportamento predefinito di Hibernate durante l'uso @SequenceGenerator
: aumenta la sequenza del database reale di uno , moltiplica questo valore per 50 ( allocationSize
valore predefinito ) e quindi utilizza questo valore come ID entità.
Questo è un comportamento errato e è in conflitto con le specifiche che dicono:
AllocationSize - (Facoltativo) L'importo di cui incrementare quando si allocano i numeri di sequenza dalla sequenza.
Per essere chiari: non mi preoccupo degli spazi tra gli ID generati.
Mi interessano gli ID che non sono coerenti con la sequenza del database sottostante. Ad esempio: qualsiasi altra applicazione (che ad esempio utilizza JDBC semplice) potrebbe voler inserire nuove righe sotto gli ID ottenuti dalla sequenza, ma tutti questi valori potrebbero essere già utilizzati da Hibernate! Follia.
Qualcuno conosce una soluzione a questo problema (senza impostare allocationSize=1
e quindi degradare le prestazioni)?
EDIT:
per rendere le cose chiare. Se l'ultimo record inserito aveva ID = 1
, allora HB usa i valori 51, 52, 53...
per le sue nuove entità MA allo stesso tempo: il valore della sequenza nel database sarà impostato su 2
. Il che può facilmente portare a errori quando altre applicazioni utilizzano quella sequenza.
D'altra parte: la specifica dice (nella mia comprensione) che la sequenza del database avrebbe dovuto essere impostata 51
e nel frattempo HB dovrebbe usare i valori dell'intervallo 2, 3 ... 50
AGGIORNAMENTO:
Come Steve Ebersole ha menzionato di seguito: il comportamento da me descritto (e anche il più intuitivo per molti) può essere abilitato impostando hibernate.id.new_generator_mappings=true
.
Grazie a tutti voi.
AGGIORNAMENTO 2:
Per i futuri lettori, di seguito puoi trovare un esempio funzionante.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ")
@SequenceGenerator(name = "USERS_SEQ", sequenceName = "SEQUENCE_USERS")
private Long id;
}
persistence.xml
<persistence-unit name="testPU">
<properties>
<property name="hibernate.id.new_generator_mappings" value="true" />
</properties>
</persistence-unit>
save
devono interrogare il database per il valore successivo della sequenza.
SequenceGenerator
Hibernate interrogherà il database solo quando la quantità di ID specificata da allocationsize
si esaurisce. Se imposti, allocationSize = 1
è il motivo per cui Hibernate interroga il DB per ogni inserimento. Cambia questo valore e hai finito.
hibernate.id.new_generator_mappings
ambientazione è davvero importante. Spero che sia l'impostazione predefinita che non devo dedicare così tanto tempo alla ricerca del motivo per cui il numero ID diventa selvaggio.