Я установил тестовое приложение с Hibernate, PostgreSQL и Spring и продолжаю сталкиваться с этой необъяснимой ошибкой.Я надеюсь, что кто-то здесь может пролить свет на эту проблему.
Моя сущность выглядит следующим образом:
@Entity
@Table(name = "something")
public class Something {
@Id
@SequenceGenerator(name = "somethingGen", sequenceName = "something_id_seq", allocationSize = 30)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "somethingGen")
@Column(name = "id", unique = true, nullable = false)
private long id;
public Something() {
}
public long getId() {
return id;
}
@Override
public String toString() {
return new StringJoiner(", ", Something.class.getSimpleName() + "[", "]")
.add("id=" + id)
.toString();
}
}
Для целей тестирования я создал репозиторий данных Spring, вставил пять записей и получил ихназад:
System.out.println("starting...");
for (int i = 0; i < 5; i++) {
repository.save(new Something());
}
repository.findAll().forEach(System.out::println);
При первом запуске этого кода он работает почти так, как ожидалось:
Something[id=1]
Something[id=2]
Something[id=3]
Something[id=4]
Something[id=5]
Второй раз, однако я получаю это исключение: org.hibernate.MappingException: The increment size of the [something_id_seq] sequence is set to [30] in the entity mapping while the associated database sequence increment size is [1].
Итак, я проверил последовательность в базе данных Postgres:
uat=# \d something_id_seq
Sequence "public.something_id_seq"
Column | Type | Value
---------------+---------+---------------------
sequence_name | name | something_id_seq
last_value | bigint | 1
start_value | bigint | 1
increment_by | bigint | 1
max_value | bigint | 9223372036854775807
min_value | bigint | 1
cache_value | bigint | 1
log_cnt | bigint | 32
is_cycled | boolean | f
is_called | boolean | t
Это первая проблема.Похоже, что Hibernate создает последовательности с неправильным значением приращения.Поэтому я изменил значение increment_by: alter sequence something_id_seq increment 30
, снова запустил свой код и в итоге получил такой вывод:
Something[id=1]
Something[id=2]
Something[id=3]
Something[id=4]
Something[id=5]
Something[id=901]
Something[id=902]
Something[id=903]
Something[id=904]
Something[id=905]
И теперь последовательность выглядит следующим образом:
---------------+---------+---------------------
sequence_name | name | something_id_seq
last_value | bigint | 31
start_value | bigint | 1
increment_by | bigint | 30
ИтакМне кажется, что новый идентификатор рассчитывается через increment_by * allocation_size + last_value
, но я ожидал, что новый идентификатор будет 30 (allocation_size * last_value
), так как я подозревал, что increment_by
и allocationSize
будут одинаковыми из-за MappingException.
Это оставляет меня с двумя вопросами:
Я ожидал идентификаторы около 0, 30, 60, 90 ... и вместо этого я получил идентификаторы около 1 и 900Javadoc SequenceGenerator утверждает, что allocSize равен the amount to increment by when allocating sequence numbers from the sequence
.Значит ли это, что increment_by
и allocationSize
не одно и то же?Как они связаны друг с другом (например, почему я вижу MappingException
) и как мне добиться ожидаемого поведения?
Исключение Mapping указывает мне, что Hibernate создает последовательности снеправильное значение приращения.Как заставить Hibernate создать правильный?
Я использую Hibernate 5.4.2.Final и PostgreSql 9.6.12 и эти настройки:
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setDatabase(Database.POSTGRESQL);
hibernateJpaVendorAdapter.setDatabasePlatform(PostgreSQL9Dialect.class.getName());
hibernateJpaVendorAdapter.setGenerateDdl(true);
Я подозреваю, что проблема может быть где-то с генератором HiLo, но для жизни я не могу понять это:
hibernate.id.new_generator_mappings=true
hibernate.id.optimizer.pooled.preferred=hilo
hibernate.schema_update.unique_constraint_strategy=RECREATE_QUIETLY