Por que o eclipselink consome todo o alocaçãoSize cada vez que é reiniciado?
-
27-09-2019 - |
Pergunta
Acabei de notar que para o id da minha entidade, o eclipselink atribui um id 1 + o anteriormente atribuído NA MESMA SESSÃO (1), ao contrário da tabela de elementos (2).Isso vai contra as expectativas da minha aplicação.
Qual é a maneira mais fácil de dizer para fazer 2?
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int objId;
E aqui está o que tenho no banco de dados:
ij> connect 'jdbc:derby:db';
ij> set schema memo;
0 Zeilen eingef?gt/aktualisiert/gel?scht
ij> select * from meaning;
OBJID |LASTPUBLI&|USR_EMAIL
-------------------------------------------------------------------------------------------------------------------------------------------------------
1 |NULL |NULL
2 |2010-10-27|NULL
51 |NULL |NULL
101 |NULL |NULL
Solução
Ao usar um GenerationType.AUTO
estratégia com Derby, o EclipseLink assume como padrão um gerador de tabela estratégia.
Então, ao gerar um Id
for necessário, EL irá pré-alocar ids de acordo com o allocationSize
(que é 50 por padrão).Para isso, primeiro atualizará a coluna que armazena o último valor gerado para incrementá-la pelo allocationSize
:
UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
bind => [50, SEQ_GEN]
E então lerá o novo valor:
SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?
bind => [SEQ_GEN]
Uma vez feito isso, EL pré-aloca um conjunto de ids usando o atual valor - alocaçãoSize + 1 como "primeiro" e valor como "último":
local sequencing preallocation for SEQ_GEN: objects: 50 , first: 1, last: 50
E servirá ids da memória até atingir o último valor e reiniciará um ciclo.
Agora, se você reiniciar a JVM, não há outra maneira segura para EL do que pré-alocar um novo conjunto de ids, "perdendo" aqueles do intervalo "anterior" que não foram usados (pense em multi-JVMs, etc.), que explica o "salto" de 2 para 51 no seu exemplo.
Se você quiser evitar isso, minha sugestão seria mudar para um IDENTITY
estratégia que é suportada pelo Derby (não acho que configurar o gerador de tabela para usar um allocationSize
de 1 seria uma boa ideia).
Não acho que configurar o gerador de tabela para usar um alocaçãoSize de 1 seja uma boa ideia.Por que não?
Por causa do impacto no desempenho, se você precisar ler a tabela de "sequência" para cada inserção.Mas por outro lado, 1) isso pode não ser uma preocupação no seu caso 2) Essa é a única estratégia que permite obter ids verdadeiramente sequenciais.
Se estiver interessado, você poderá configurar isso globalmente usando o table-generator
elemento no descritor XML.
EL desencoraja fortemente a estratégia de identidade, além de parecer que existem minas (porque você deve esperar para confirmar antes de ler o valor, algo que posso estar fazendo em algum lugar).
Bem, não posso confirmar para EL (não vou testar isso agora), mas o Hibernate realiza uma inserção imediata em persist
quando você usa um IDENTITY
estratégia.Achei que EL se comportaria da mesma maneira.Mas posso estar errado, isso não parece obrigatório pelas especificações.