【问题标题】:JPA - PK attribute issue after INSERTJPA - 插入后的 PK 属性问题
【发布时间】:2020-03-25 19:53:59
【问题描述】:

JPA(休眠提供程序)和 Postgres 11

我的 Id 属性具有此配置(它是单列/属性 PK)。

由于某种原因,在对该表执行 INSERT 后,JPA 调用

select currval('yb.asset_store_id_seq')

我猜(我不确定)这样做是为了刷新新插入实体的 ID,或者可能出于某种类似原因。

但是没有这样的顺序。我的序列名为yb.asset_store_seq,我的表名为yb.asset_store。 我的实体类是AssetStore

那么...我该如何解决这个问题?基本上,JPA 不知何故编造了这个序列名称。还是我错过了什么?!

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

在数据库级别,序列由表拥有。

这是堆栈跟踪。

    Hibernate: 
        select
            currval('yb.asset_store_id_seq')
    Mar 25, 2020 3:45:02 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
    WARN: SQL Error: 0, SQLState: 42P01
    Mar 25, 2020 3:45:02 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
    ERROR: ERROR: relation "yb.asset_store_id_seq" does not exist
      Position: 16
    Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet


    ...................


        Caused by: org.postgresql.util.PSQLException: ERROR: relation "yb.asset_store_id_seq" does not exist
  Position: 16
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308)

【问题讨论】:

  • this
  • @SternK 谢谢...你的意思是我应该使用hibernate.jdbc.use_get_generated_keys=true 或...?这似乎是一个非 JPA 标准,即一些休眠特定属性......这是解决方案还是......?
  • 是的,如果你的 jdbc 驱动支持的话。它将允许摆脱 select currval('yb.asset_store_id_seq') 查询。
  • 这似乎可行...但每个问题都会带来 3-4 个新问题 :) 谢谢。
  • JPA 并没有定义一切(它会成为一个非常臃肿的标准),因此您还需要/可以拥有特定于实现(Hibernate、EclipseLink 等)的东西。

标签: java postgresql hibernate jpa


【解决方案1】:

首先休眠documentation根本不建议使用GenerationType.IDENTITY策略:

重要的是要意识到,使用 IDENTITY 列会产生一种运行时行为,其中实体行必须在标识符值已知之前物理插入。

这可能会弄乱扩展的持久性上下文(长时间的对话)。由于运行时强制/不一致,Hibernate 建议使用其他形式的标识符值生成(例如 SEQUENCE)。

选择 IDENTITY 生成还有另一个重要的运行时影响:Hibernate 将无法为使用 IDENTITY 生成的实体批处理 INSERT 语句。

但是如果你不能改变它,你使用JDBC3+驱动和JRE1.4+。我建议明确定义:

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

因为根据this

hibernate.jdbc.use_get_generated_keys(例如真或假)

允许 Hibernate 在插入后使用 JDBC3 PreparedStatement.getGeneratedKeys() 检索本机生成的密钥。您需要 JDBC3+ 驱动程序和 JRE1.4+。如果您的驱动程序与 Hibernate 标识符生成器有问题,请禁用此属性。 默认情况下,它会尝试从连接元数据中检测驱动程序功能。

这样可以避免你的问题。

【讨论】:

  • 谢谢。从第一部分我一个字都听不懂。我不确定写它的人是否也理解它。 “强加一种运行时行为,其中实体行必须在标识符值已知之前物理插入”>>>这对我来说听起来像是一个好处,而不是一个缺点......事实上我希望我的 RDBMS 生成我的密钥,谁别的? “Hibernate 将无法使用 IDENTITY 生成为实体批处理 INSERT 语句”>>> 这是什么意思,他们指的是哪些场景,知道吗?!关于第二部分,非常感谢,它真的很有帮助。
  • “由于运行时强加/不一致” 这也是什么意思?在幕后,即使我使用 IDENTITY 策略,仍然会调用我的序列来生成 Id 列的值。我已经检查过了。无论如何......即使我找到并阅读了它,我也没有得到这个文档文本。再次感谢!
  • 至于long conversationsthis
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-20
  • 2023-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-10
  • 1970-01-01
相关资源
最近更新 更多