为什么Hibernate偶尔会在persistent中执行select curval



有时,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');

但通常不执行CCD_ 1。对此有什么解释吗?

顺便说一句,我的问题与此非常相似,但问题中的解决方案对我不起作用。

注:

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。方言:org.hibernate.dialect.PostgreSQL9方言
  • Hibernate版本:5.4.5.最终版本
  • PostgreSQL JDBC驱动程序:PostgreSQL-9.4

根据hibernate文档:

2.6.10.使用IDENTITY列

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

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

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

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

您没有这样做,所以hibernate以某种方式将其值视为false。然后hibernate检查dialect.getIdentityColumnSupport().supportsInsertSelectIdentity()的值。你的案子是false。最后一条路是冬眠。请参阅PostgreSQL81IdentityColumnSupport类的实现。getIdentitySelectString方法生成的sql与您抱怨的完全相同。

最新更新