3

有时,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
  • 休眠版本:5.4.5.Final
  • PostgreSQL JDBC 驱动程序:postgresql-9.4
4

1 回答 1

3

根据休眠文档

2.6.10。使用 IDENTITY 列

为了实现基于 IDENTITY 列的标识符值生成,Hibernate 使用其org.hibernate.id.IdentityGeneratorid 生成器,该生成器期望标识符由 INSERT 生成到表中。IdentityGenerator 了解可以检索 INSERT 生成的值的 3 种不同方式:

  1. 如果 Hibernate 认为 JDBC 环境支持java.sql.Statement#getGeneratedKeys,那么该方法将用于提取 IDENTITY 生成的密钥。
  2. 否则,如果Dialect#supportsInsertSelectIdentity报告为真,Hibernate 将使用方言特定的 INSERT+SELECT 语句语法。
  3. 否则,Hibernate 将期望数据库支持通过单独的 SQL 命令请求最近插入的 IDENTITY 值的某种形式,如Dialect#getIdentitySelectString

您可以java.sql.Statement#getGeneratedKeys通过以下方式明确指定:

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

您不这样做,因此,hibernate 以某种方式将其值视为false. 然后休眠检查dialect.getIdentityColumnSupport().supportsInsertSelectIdentity(). 这是false为你的情况。然后通过最后一种方式休眠。请参阅PostgreSQL81IdentityColumnSupport类的实现。getIdentitySelectString方法生成的 sql 与您抱怨的完全相同。

于 2020-03-05T20:45:55.993 回答