Почему Hibernate иногда выполняет select currval в persist? - PullRequest
2 голосов
/ 02 марта 2020

Иногда и кажется случайным образом Hibernate выполняет запрос во время операции постоянства:

select currval('MY_TABLE_NAME_id_seq');

Объект:

@Entity
@Table(name = "MY_TABLE_NAME")
public class MyEntity {

   @Id
   @Column(name = "ID", unique = true, nullable = false)
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   private Long id;

}

Код:

@Transactional
public void persistMyEntity(String name) {
   MyEntity entity= new MyEntity (name);
   sessionFactory.getCurrentSession().persist(entity);
}

Сгенерировано sql:

insert into MY_TABLE_NAME(name) values ('xyz');

select currval('MY_TABLE_NAME_id_seq');

Но обычно select currval не выполняется. Есть ли какое-либо объяснение по этому поводу?

Кстати, мой вопрос очень похож на этот , но решение вопроса не работает для меня.

Примечание:

My_TABLE_NAME ddl sql:

CREATE TABLE my_table_name (
   id bigserial NOT NULL,
   name character varying(256) NOT NULL,
   CONSTRAINT my_table_name_id PRIMARY KEY (id)
);

Свойства гибернации:

Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", HIBERNATE_DIALECT);
hibernateProperties.put("hibernate.show_sql", HIBERNATE_SHOW_SQL);
hibernateProperties.put("hibernate.hbm2ddl.auto", "none");
hibernateProperties.put("hibernate.connection.release_mode", "auto");
hibernateProperties.put("hibernate.archive.autodetection", ARCHIVE_AUTODETECTION);
hibernateProperties.put("hibernate.format_sql", true);
hibernateProperties.put("hibernate.use_sql_comments", true);
hibernateProperties.put("hibernate.generate_statistics", false);
hibernateProperties.put("hibernate.jdbc.use_scrollable_resultset", true);
hibernateProperties.put("hibernate.jdbc.use_streams_for_binary", true);
hibernateProperties.put("hibernate.jdbc.batch_size", 20);
hibernateProperties.put("hibernate.order_inserts", true);
hibernateProperties.put("hibernate.order_updates", true);
hibernateProperties.put("hibernate.jdbc.batch_versioned_data ", true);
hibernateProperties.put("hibernate.cache.region_prefix", "hibernate.cache");
hibernateProperties.put("hibernate.cache.use_query_cache", false);
hibernateProperties.put("hibernate.cache.use_second_level_cache", false);
sessionFactoryBean.setHibernateProperties(hibernateProperties);
  • PostgreSQL версия: 11.5.
  • hibernate.dialect: org.hibernate.dialect.PostgreSQL9Dialect
  • Версия Hibernate: 5.4.5. Финал
  • PostgreSQL JDB C Драйвер: postgresql -9.4

1 Ответ

2 голосов
/ 05 марта 2020

В соответствии со спящей документацией :

2.6.10. Использование столбцов IDENTITY

Для реализации генерации значения идентификатора на основе столбцов IDENTITY Hibernate использует свой генератор идентификатора org.hibernate.id.IdentityGenerator, который ожидает, что идентификатор будет сгенерирован INSERT в таблицу. IdentityGenerator понимает 3 различных способа получения значения, созданного INSERT:

  1. Если Hibernate считает, что среда JDB C поддерживает java.sql.Statement#getGeneratedKeys, то этот подход будет использоваться для извлечения ключей, сгенерированных IDENTITY. .
  2. В противном случае, если Dialect#supportsInsertSelectIdentity сообщает об истинном, Hibernate будет использовать спецификацию диалекта c INSERT + SELECT.
  3. В противном случае Hibernate будет ожидать, что база данных поддерживает какую-либо форму запроса. для последнего добавленного значения IDENTITY с помощью отдельной команды SQL, как указано Dialect#getIdentitySelectString

Вы можете явно указать java.sql.Statement#getGeneratedKeys следующим образом:

<property name="hibernate.jdbc.use_get_generated_keys">true</property>

Вы этого не делаете, поэтому hibernate как-то трактует его значение как false. Затем hibernate проверяет значение dialect.getIdentityColumnSupport().supportsInsertSelectIdentity(). Это false для вашего случая. И тогда спящий режим следует по последнему пути. См. Реализацию класса PostgreSQL81IdentityColumnSupport . Метод getIdentitySelectString создает точно такой же sql, на который вы жаловались.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...