При работе с фреймворком Hibernate и базой данных H2 можно наблюдать странную картину при назначении id записи в базе данных.
Например, может наблюдаться такая последовательность id-шников:
1 2 3 4 5 6 7 8 33 34 35 65 ...
Красным здесь отмечен каждый запуск приложения.
Получается, в первый запуск мы вставили записи: 1 2 3 4 5 6 7 8
второй запуск - 33 34 35
третий запуск - 65 ...
Такое ощущение, что мы вставляли подряд записи, а потом часть из них удалили. Но нет, записи не удалялись.
Покопавшись и перепробовав несколько баз данных (MySQL, HSQLBD, H2), я выяснил, что такое происходит только с базой H2. Если присмотреться к цифрам, то можно увидеть, что в базе при каждой 32-й записи под индексы резервируется еще 32.
Мы вставляем запись №1, зарезервировалось 32. Перезапускаем приложение, вставляем опять запись, 32 у нас уже как бы есть (были зарезервированы прошлый запуск), значит вставится запись под номером 33. И т.д.
Какая причина резервирования
Причина простая. В базе H2 по умолчанию стоит кеширование, размер кеша = 32 записи. Кеширование используется для предотвращения потери данных при падении базы (или неправильном завершении приложения).
Почитав форумы и разные ресурсы нашлось несколько решений проблемы с генерацией и резервированием.
Решение 1
Добавить вот такие аннотации к нашему полю id:
Решение 5 (неопробованное)
Можно найти как задать размер кеша для базы H2, сделать это и написать в комментарии к статье, как вы это сделали :)
Например, может наблюдаться такая последовательность id-шников:
1 2 3 4 5 6 7 8 33 34 35 65 ...
Красным здесь отмечен каждый запуск приложения.
Получается, в первый запуск мы вставили записи: 1 2 3 4 5 6 7 8
второй запуск - 33 34 35
третий запуск - 65 ...
Такое ощущение, что мы вставляли подряд записи, а потом часть из них удалили. Но нет, записи не удалялись.
Покопавшись и перепробовав несколько баз данных (MySQL, HSQLBD, H2), я выяснил, что такое происходит только с базой H2. Если присмотреться к цифрам, то можно увидеть, что в базе при каждой 32-й записи под индексы резервируется еще 32.
Мы вставляем запись №1, зарезервировалось 32. Перезапускаем приложение, вставляем опять запись, 32 у нас уже как бы есть (были зарезервированы прошлый запуск), значит вставится запись под номером 33. И т.д.
Какая причина резервирования
Причина простая. В базе H2 по умолчанию стоит кеширование, размер кеша = 32 записи. Кеширование используется для предотвращения потери данных при падении базы (или неправильном завершении приложения).
Почитав форумы и разные ресурсы нашлось несколько решений проблемы с генерацией и резервированием.
Решение 1
Добавить вот такие аннотации к нашему полю id:
@Id
@Column(name="...")
@GeneratedValue(strategy=GenerationType.TABLE, generator="generatorName")
@TableGenerator(name="generatorName", allocationSize=1)
private Long id;
generatorName - может быть любым.
После этого должна быть нормальная последовательность при автоматической генерации id (без пропусков).
Решение 2
Использовать другую базу данных, не H2, где нет кеширования.
Решение 3 (неопробованное)
@Id
@GenericGenerator(name="kaugen" , strategy="increment")
@GeneratedValue(generator="kaugen")
@Column(name="proj_id")
@GenericGenerator(name="kaugen" , strategy="increment")
@GeneratedValue(generator="kaugen")
@Column(name="proj_id")
private Long id;
Eclipse будет выдавать ошибку, которая решается так:
Вариант 1
или так
Вариант 2
Решение 4 (неопробованное)
Можно написать свой генератор для id (ссылка на ресурс в конце).
Вариант 1
или так
Вариант 2
Решение 4 (неопробованное)
Можно написать свой генератор для id (ссылка на ресурс в конце).
Решение 5 (неопробованное)
Можно найти как задать размер кеша для базы H2, сделать это и написать в комментарии к статье, как вы это сделали :)
Ресурс, откуда взяты примеры:
Там же можно найти, как написать свой генератор.
Спасибо большое, очень полезная статья.
ОтветитьУдалитьРад, что статья стала Вам полезной.
УдалитьСпасибо!
Удалить