I have two objects with one-to-many relationship between them that I implemented as follows:
@Entity
@Table(name = "details")
public class MainDetails {
@Id
@Column(name = "details_id")
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
// Some other fields here - omitted
@OneToMany(fetch = FetchType.LAZY,
mappedBy = "details",
targetEntity = State.class,
cascade = CascadeType.ALL)
@OrderBy("timestamp DESC")
private List<State> states;
}
And the second one:
@Entity
@Table(name = "state")
public class State {
@Id
@Column(name = "state_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "details_id")
private MainDetails details;
// Other fields omitted (including timestamp)
}
I call a save() method on the MainDetails object. The method looks like this:
public T save(T obj) { // The T in this case is MainDetails
entityManager.persist(obj);
entityManager.flush();
return obj;
}
But then I get this exception:
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "details_pkey" Detail: Key (details_id)=(8) already exists.
My persistence.xml looks like this:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="my-persistence-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!-- Annotated entity classes -->
<class>com.company.entity.MainDetails</class>
<class>com.company.entity.State</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
</properties>
</persistence-unit>
</persistence>
My spring context looks like this:
@EnableJpaRepositories(basePackages = {"com.company.dao", "com.company.*.dao"})
@EnableTransactionManagement(proxyTargetClass = true)
@Import(BasicConfig.class)
public class DbConfig {
@Value("${db.connection_string}")
private String connectionString;
@Value("${db.user_name}")
private String dbUserName;
@Value("${db.password}")
private String dbPassword;
@Bean
public DataSource dataSource() {
DriverManagerDataSource driver = new DriverManagerDataSource();
driver.setDriverClassName("org.postgresql.Driver");
driver.setUrl(connectionString);
driver.setUsername(dbUserName);
driver.setPassword(dbPassword);
return driver;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(true);
adapter.setGenerateDdl(true);
adapter.setDatabase(Database.POSTGRESQL);
return adapter;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPersistenceUnitName("my-persistence-unit");
factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
return factoryBean;
}
@Bean
public JpaTransactionManager transactionManager() throws ClassNotFoundException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
I have two objects with one-to-many relationship between them that I implemented as follows:
@Entity
@Table(name = "details")
public class MainDetails {
@Id
@Column(name = "details_id")
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
// Some other fields here - omitted
@OneToMany(fetch = FetchType.LAZY,
mappedBy = "details",
targetEntity = State.class,
cascade = CascadeType.ALL)
@OrderBy("timestamp DESC")
private List<State> states;
}
And the second one:
@Entity
@Table(name = "state")
public class State {
@Id
@Column(name = "state_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "details_id")
private MainDetails details;
// Other fields omitted (including timestamp)
}
I call a save() method on the MainDetails object. The method looks like this:
public T save(T obj) { // The T in this case is MainDetails
entityManager.persist(obj);
entityManager.flush();
return obj;
}
But then I get this exception:
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "details_pkey" Detail: Key (details_id)=(8) already exists.
My persistence.xml looks like this:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="my-persistence-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!-- Annotated entity classes -->
<class>com.company.entity.MainDetails</class>
<class>com.company.entity.State</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
</properties>
</persistence-unit>
</persistence>
My spring context looks like this:
@EnableJpaRepositories(basePackages = {"com.company.dao", "com.company.*.dao"})
@EnableTransactionManagement(proxyTargetClass = true)
@Import(BasicConfig.class)
public class DbConfig {
@Value("${db.connection_string}")
private String connectionString;
@Value("${db.user_name}")
private String dbUserName;
@Value("${db.password}")
private String dbPassword;
@Bean
public DataSource dataSource() {
DriverManagerDataSource driver = new DriverManagerDataSource();
driver.setDriverClassName("org.postgresql.Driver");
driver.setUrl(connectionString);
driver.setUsername(dbUserName);
driver.setPassword(dbPassword);
return driver;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(true);
adapter.setGenerateDdl(true);
adapter.setDatabase(Database.POSTGRESQL);
return adapter;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPersistenceUnitName("my-persistence-unit");
factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
return factoryBean;
}
@Bean
public JpaTransactionManager transactionManager() throws ClassNotFoundException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
I have the following problem
@Entity
@Table(name="tb_pessoa", schema="public")
@Inheritance(strategy = InheritanceType.JOINED)
public class Pessoa implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name = "tb_pessoa_id_seq", sequenceName = "tb_pessoa_id_seq", schema="public")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "tb_pessoa_id_seq")
@Column(name = "id", nullable = false)
private Integer id;
...
@Entity
@Table(name="tb_pessoafisica", schema="public")
@PessoaFisicaAnnotation
@PrimaryKeyJoinColumn(name = "id")
public class PessoaFisica extends Pessoa implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "email")
private String email;
...
Assuming the Pessoa table has records with id 1 to 500. When I run the code below:
PessoaFisica pessoaFisica = new PessoaFisica();
pessoaFisica.setEmail("teste@123.com");
...
em.persist(pessoa);
It’s happening the following error:
17:26:13,613 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--10.36.1.49-8180-1) ERROR: duplicate key value violates unique constraint "tb_pessoa_pkey"
Detalhe: Key (id)=(438) already exists.
17:26:13,614 WARN [com.arjuna.ats.arjuna] (http--10.36.1.49-8180-1) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffff7f000101:-7f6ae4e3:558080ed:4f, org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization@331af73a >: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: ERROR: duplicate key value violates unique constraint "tb_pessoa_pkey"
Detalhe: Key (id)=(438) already exists.
why is trying to use the id 438 and not 501???
Does anyone know what might be happening?
thank you very much
CREATE TABLE tb_pessoa
(
id integer NOT NULL,
CONSTRAINT tb_pessoa_pkey PRIMARY KEY (id)
)
CREATE TABLE tb_pessoafisica
(
email character varying(64) NOT NULL,
CONSTRAINT tb_pessoafisica_pkey PRIMARY KEY (id),
CONSTRAINT fkee8c050f70415778 FOREIGN KEY (id)
REFERENCES tb_pessoa (id) MATCH SIMPLE
)
CREATE SEQUENCE tb_pessoa_id_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 500
CACHE 1;
Log Hibernate:
07:50:52,463 INFO [stdout] (http--10.36.1.49-8180-2) Hibernate:
07:50:52,463 INFO [stdout] (http--10.36.1.49-8180-2) select
07:50:52,464 INFO [stdout] (http--10.36.1.49-8180-2) nextval ('public.tb_pessoa_id_seq')
07:50:52,497 INFO [stdout] (http--10.36.1.49-8180-2) Hibernate:
07:50:52,498 INFO [stdout] (http--10.36.1.49-8180-2) insert
07:50:52,499 INFO [stdout] (http--10.36.1.49-8180-2) into
07:50:52,499 INFO [stdout] (http--10.36.1.49-8180-2) public.tb_pessoa
07:50:52,500 INFO [stdout] (http--10.36.1.49-8180-2) (id)
07:50:52,500 INFO [stdout] (http--10.36.1.49-8180-2) values
07:50:52,501 INFO [stdout] (http--10.36.1.49-8180-2) (?)
07:50:52,519 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--10.36.1.49-8180-2) SQL Error: 0, SQLState: 23505
07:50:52,521 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--10.36.1.49-8180-2) ERROR: duplicate key value violates unique constraint "tb_pessoa_pkey"
Detalhe: Key (id)=(438) already exists.
I have the following problem
@Entity
@Table(name="tb_pessoa", schema="public")
@Inheritance(strategy = InheritanceType.JOINED)
public class Pessoa implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name = "tb_pessoa_id_seq", sequenceName = "tb_pessoa_id_seq", schema="public")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "tb_pessoa_id_seq")
@Column(name = "id", nullable = false)
private Integer id;
...
@Entity
@Table(name="tb_pessoafisica", schema="public")
@PessoaFisicaAnnotation
@PrimaryKeyJoinColumn(name = "id")
public class PessoaFisica extends Pessoa implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "email")
private String email;
...
Assuming the Pessoa table has records with id 1 to 500. When I run the code below:
PessoaFisica pessoaFisica = new PessoaFisica();
pessoaFisica.setEmail("teste@123.com");
...
em.persist(pessoa);
It’s happening the following error:
17:26:13,613 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--10.36.1.49-8180-1) ERROR: duplicate key value violates unique constraint "tb_pessoa_pkey"
Detalhe: Key (id)=(438) already exists.
17:26:13,614 WARN [com.arjuna.ats.arjuna] (http--10.36.1.49-8180-1) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffff7f000101:-7f6ae4e3:558080ed:4f, org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization@331af73a >: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: ERROR: duplicate key value violates unique constraint "tb_pessoa_pkey"
Detalhe: Key (id)=(438) already exists.
why is trying to use the id 438 and not 501???
Does anyone know what might be happening?
thank you very much
CREATE TABLE tb_pessoa
(
id integer NOT NULL,
CONSTRAINT tb_pessoa_pkey PRIMARY KEY (id)
)
CREATE TABLE tb_pessoafisica
(
email character varying(64) NOT NULL,
CONSTRAINT tb_pessoafisica_pkey PRIMARY KEY (id),
CONSTRAINT fkee8c050f70415778 FOREIGN KEY (id)
REFERENCES tb_pessoa (id) MATCH SIMPLE
)
CREATE SEQUENCE tb_pessoa_id_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 500
CACHE 1;
Log Hibernate:
07:50:52,463 INFO [stdout] (http--10.36.1.49-8180-2) Hibernate:
07:50:52,463 INFO [stdout] (http--10.36.1.49-8180-2) select
07:50:52,464 INFO [stdout] (http--10.36.1.49-8180-2) nextval ('public.tb_pessoa_id_seq')
07:50:52,497 INFO [stdout] (http--10.36.1.49-8180-2) Hibernate:
07:50:52,498 INFO [stdout] (http--10.36.1.49-8180-2) insert
07:50:52,499 INFO [stdout] (http--10.36.1.49-8180-2) into
07:50:52,499 INFO [stdout] (http--10.36.1.49-8180-2) public.tb_pessoa
07:50:52,500 INFO [stdout] (http--10.36.1.49-8180-2) (id)
07:50:52,500 INFO [stdout] (http--10.36.1.49-8180-2) values
07:50:52,501 INFO [stdout] (http--10.36.1.49-8180-2) (?)
07:50:52,519 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--10.36.1.49-8180-2) SQL Error: 0, SQLState: 23505
07:50:52,521 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--10.36.1.49-8180-2) ERROR: duplicate key value violates unique constraint "tb_pessoa_pkey"
Detalhe: Key (id)=(438) already exists.
Есть таблица в БД PostgreSql. У этой таблицы есть ограничение на уникальность для id. Сохраняю сущности в БД посредством Hibernate.
Код Entity:
@Entity
@Table(name = "cinema_movie")
public class Cinema_Movie {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "cinema_id")
private String cinemaId;
@Column(name = "movie_id")
private String movieId;
Геттеры и сеттеры, плюс конструктор прилагаются. Не писал для сокращения кода.
Код сохранения в БД:
public void save() {
CinemaMovie cinema_movie = new CinameMovie();
cinema_movie.setCinemaId("random");
cinema_movie.setMovieId("random")
session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
session.save(cinema_movie);
}
Ну и в HibernateSessionFactoryUtil ничего особенного нет:
public static SessionFactory getSessionFactory() {
logger.debug("Start method getSessionFactory() at HibernateSessionFactoryUtil.class");
if (sessionFactory == null) {
try {
Configuration configuration = new Configuration().configure();
configuration.addAnnotatedClass(Cinema_Movie.class);
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
} catch (Exception e) {
logger.error("Error at method getSessionFactory() at HibernateSessionFactoryUtil.class: ", e);
}
}
logger.debug("End of method getSessionFactory() at HibernateSessionFactoryUtil.class");
return sessionFactory;
}
И соответственно, метод save() вызывается переодически в разное время в программе. Изменения в БД в данную таблицу вносились руками, удалялись некоторые записи, т.к. программа только на стадии разработки.
Вопрос в следующем:
Как происходит генерация уникальных значений в Hibernate, и почему переодически я получаю ошибку:
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности
?
А так же, как избежать данной ошибки, т.е. чтобы Hibernate точно гененрировал уникальные ID, которых еще нет в БД? Только дополнительной проверкой? Или сделать другой primary key, который самому генерировать? Или же есть какая то возможность исключения такой ошибки с помощью инструментов Hibernate?
#java #postgresql #hibernate #spring-boot #jpa
#java #postgresql #впасть в спящий режим #пружинный ботинок #jpa
Вопрос:
Повторяющееся значение ключа нарушает ограничение уникальности после сохранения объекта @ManyToOne
Я попытался сохранить объект A, у которого есть другой объект B с уникальным именем поля с помощью spring-data. Если B уже существует в БД, то будет выдано исключение «дублирующее значение ключа нарушает уникальное ограничение «b_name_key». Подробно: Ключ (b_name)=(someName) уже существует.
create table b
(
b_id serial primary key,
b_name varchar(3) not null unique
);
create table a
(
a_id serial primary key,
b_id int references b (b_id) not null,
);
@Entity
@Getter
@Setter
public class B implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long b_id;
@Column(name = "b_name", unique = true)
private String bName;
public B(String bName) {
this.bName = bName;
}
public B() {}
@Override
public String toString() {
return "...";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
B b = (B) o;
return Objects.equals(bName, b.bName);
}
@Override
public int hashCode() {
return Objects.hash(bName);
}
}
@Entity
@Getter
@Setter
public class a implements java.io.Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long a_id;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "b_id")
private B b;
public a() {
}
public a(B b ) {
this.b = b;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
a a = (a) o;
return Objects.equals(b, a.b)
}
@Override
public int hashCode() {
return Objects.hash(b);
}
}
@Repository
public interface ARepository extends JpaRepository<Metastasis, Long> {}
@Controller
public class AController {
private final ARepository aRepository;
public AController(ARepository aRepository) {
this.aRepository = aRepository;
}
@GetMapping("/test")
public String showaddUserForm() {
B b = new B("SomeName");
A a = new A(b);
aRepository.save(a);
return "index";
}
}
@SpringBootApplication
@EnableJpaRepositories(basePackages = "...repositories")
@EnableTransactionManagement
@EntityScan(basePackages = "....entities")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Я получаю org.postgresql.util.PSQLException: ОШИБКА: повторяющееся значение ключа нарушает уникальное ограничение «b_name_key»
Подробно: ключ (b_name) = (SomeName) уже существует.
Ответ №1:
Это нормально. Поскольку a объект является новым, операция сохранения будет каскадно передана b объекту, который также является новым, и завершится неудачей, поскольку в базе данных уже есть запись с этим ключом.
Попробуйте что-то вроде:
// find for B
B b = bRepository.findById(..);
// if not found, create one
if (b == null) {
b = new B("SomeName");
}
A a = new A(b);
aRepository.save(a);
Комментарии:
1. Почему спящий режим не может справиться с этим сам?
Есть таблица в БД PostgreSql. У этой таблицы есть ограничение на уникальность для id. Сохраняю сущности в БД посредством Hibernate.
Код Entity:
@Entity
@Table(name = "cinema_movie")
public class Cinema_Movie {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "cinema_id")
private String cinemaId;
@Column(name = "movie_id")
private String movieId;
Геттеры и сеттеры, плюс конструктор прилагаются. Не писал для сокращения кода.
Код сохранения в БД:
public void save() {
CinemaMovie cinema_movie = new CinameMovie();
cinema_movie.setCinemaId("random");
cinema_movie.setMovieId("random")
session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
session.save(cinema_movie);
}
Ну и в HibernateSessionFactoryUtil ничего особенного нет:
public static SessionFactory getSessionFactory() {
logger.debug("Start method getSessionFactory() at HibernateSessionFactoryUtil.class");
if (sessionFactory == null) {
try {
Configuration configuration = new Configuration().configure();
configuration.addAnnotatedClass(Cinema_Movie.class);
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
} catch (Exception e) {
logger.error("Error at method getSessionFactory() at HibernateSessionFactoryUtil.class: ", e);
}
}
logger.debug("End of method getSessionFactory() at HibernateSessionFactoryUtil.class");
return sessionFactory;
}
И соответственно, метод save() вызывается переодически в разное время в программе. Изменения в БД в данную таблицу вносились руками, удалялись некоторые записи, т.к. программа только на стадии разработки.
Вопрос в следующем:
Как происходит генерация уникальных значений в Hibernate, и почему переодически я получаю ошибку:
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности
?
А так же, как избежать данной ошибки, т.е. чтобы Hibernate точно гененрировал уникальные ID, которых еще нет в БД? Только дополнительной проверкой? Или сделать другой primary key, который самому генерировать? Или же есть какая то возможность исключения такой ошибки с помощью инструментов Hibernate?
Приложение на основе My Spring Data (JPA / Hibernate) при увеличении нагрузки при сохранении новых сущностей в Postgres вызывает следующее исключение: org.postgresql.util.PSQLException: ОШИБКА: повторяющееся значение ключа нарушает уникальное ограничение «hibernate_sequences_pkey»
Стратегия для id определяется следующим образом:
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "ID")
public Long getId() {
return id;
}
Я знаю, что эта стратегия не является идеальным решением для Postgres, но является ли это причиной исключения выше?
Нагрузка создается с использованием маршрута Apache Camel с разделителем, выполняющим вставки параллельно в нескольких потоках.
2 ответа
Лучший ответ
После некоторых тестов действительно кажется, что проблема вызвана strategy = GenerationType.TABLE. После изменения на strategy = GenerationType.SEQUENCE проблемы, описанные выше с дублированием ключей, исчезли.
@Id
@SequenceGenerator(name = Consts.VEHICLE_ATTR_ID_SEQ,
sequenceName = Consts.VEHICLE_ATTR_ID_SEQ,
allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = Consts.VEHICLE_ATTR_ID_SEQ)
@Column(name = "ID", updatable = false)
public Long getId() {
return id;
}
4
Adam Boczek
7 Дек 2017 в 08:30
При переходе с Hibernate 4 на 5.3.1 (Wildfly 14.0.1) я также столкнулся с проблемой, связанной с сообщением об ошибке «повторяющееся значение ключа нарушает уникальное ограничение» hibernate_sequences_pkey. После исследования исходного кода Hibernate 5.3.1 я смог избавиться ошибки с помощью strategy = GenerationType.TABLE (я также знаю, что эта стратегия не является идеальным решением). Основная проблема была в классе TableGenerator. Для решения проблемы вы должны дополнительно использовать аннотацию GenericGenerator, например:
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = TableGenerator.DEF_TABLE)
@GenericGenerator(name = TableGenerator.DEF_TABLE, strategy
= "org.hibernate.id.enhanced.TableGenerator", parameters = {
@Parameter(name = TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, value = "true")})
@Column(name="id")
private Integer id;
Установка для параметра TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY истинного значения (поскольку по умолчанию он имеет ложное значение, и в этом случае Hibernate будет использовать имя сегмента «по умолчанию» в таблице hibernate_sequences вместо имен таблиц).Вы также должны установить для свойства hibernate.model.generator_name_as_sequence_name значение false, чтобы иметь только одну таблицу hibernate_sequences, иначе Hibernate будет использовать имена генераторов в качестве имен для таблиц последовательностей (согласно https://github.com/hibernate/hibernate-orm/commit/9a75fa8d979185b6014a814bf3ffd09e32143939#diff-936141a440957cd8a9c4a93a744e92a0 меняется). Дополнительно (но не обязательно) вы также можете установить для свойства hibernate.id.generator.stored_last_used значение false (https://github.com/hibernate/hibernate-orm/commit/9af565510064635dba7e48087ab4e8f5ef439f0d, потому что:
Чтобы соответствовать спецификациям JPA, значение, хранимое Hibernate 5.3 в таблице, используемой
javax.persistence.TableGenerator— последнее сгенерированное значение. В предыдущих версиях Hibernate вместо этого сохранялось следующее значение. используемый.Для обратной совместимости новый параметр,
hibernate.id.generator.stored_last_used, было введено, что дает возможность вернуться к прежнему режиму гибернации. Существующие приложения, переходящие на версию 5.3 и использующие @TableGenerator, имеют установитьhibernate.id.generator.stored_last_usedнаfalse
0
Dmitrii
14 Апр 2020 в 10:43