当前位置: 首页 > 面试题库 >

Hibernate无法获取下一个序列值

袁谭三
2023-03-14
问题内容

我有gwt应用程序在后端连接到postgres
DB,并且有一个Java类’Judgement’映射了数据库中的’judgements’表,当我尝试将判断持久化到db时,它引发了以下错误:

Caused by: org.hibernate.exception.SQLGrammarException: could not get next sequence value
...
Caused by: org.postgresql.util.PSQLException: ERROR: relation "hibernate_sequence" does not exist

我的审判课看起来像这样

@Entity
@Table(name = "JUDGEMENTS")
public class Judgement implements Serializable, Cloneable {

    private static final long serialVersionUID = -7049957706738879274L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "JUD_ID")
    private Long _judId;
...

我的表判断是:

   Column    |            Type             |                        Modifiers                        
-------------+-----------------------------+---------------------------------------------------------
 jud_id      | bigint                      | not null default nextval('judgements_id_seq'::regclass)
 rating      | character varying(255)      | 
 last_update | timestamp without time zone | 
 user_id     | character varying(255)      | 
 id          | integer                     | 
Indexes:
    "judgements_pkey" PRIMARY KEY, btree (jud_id)
Foreign-key constraints:
    "judgements_id_fkey" FOREIGN KEY (id) REFERENCES recommendations(id)
    "judgements_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(user_id)

我在数据库中有一个SEQUENCE名称’judgements_id_seq’

谁能告诉我怎么了???谢谢。


问题答案:

Hibernate的PostgreSQL方言不是很聪明。它不了解您的每个串行序列,并假设可以使用一个全局数据库范围的序列“
hibernate_sequence”。

更新
:似乎在GenerationType.IDENTITY指定时,较新的Hibernate版本可能会使用默认的每表顺序。请测试您的版本,如果适用,请使用此版本而不是下面的版本。)

您需要更改映射以显式指定每个序列。这很烦人,重复且毫无意义。

@Entity
@Table(name = "JUDGEMENTS")
public class Judgement implements Serializable, Cloneable {

    private static final long serialVersionUID = -7049957706738879274L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="judgements_id_seq")
    @SequenceGenerator(name="judgements_id_seq", sequenceName="judgements_id_seq", allocationSize=1)
    @Column(name = "JUD_ID")
    private Long _judId;
...

allocationSize=1是非常重要的。如果您忽略它,Hibernate会盲目地假设序列是用定义的,INCREMENT 50因此当它从序列中获取一个值时,它可以使用该值 及其下的49个值
作为唯一的生成键。如果您的数据库序列增加1(默认值),那么当Hibernate尝试重用现有密钥时,这将导致唯一违规。

请注意,一次获取一个密钥 导致每个插入的额外往返行程。据我所知,Hibernate无法INSERT ... RETURNING用于有效地返回生成的键,显然也不能使用JDBC生成的键接口。如果您告诉它使用序列,它将调用nextval来获取值,然后insert显式地获取该值,从而导致两次往返。为了减少开销,您可以在具有大量插入的键序列上设置更大的增量,记住要在映射
基础数据库序列上进行设置。这将导致Hibernate的调用nextval频率降低,并缓存键块以随其发送。

我敢肯定,从以上内容可以看出,我不同意这里所做的Hibernate设计选择,至少从与PostgreSQL一起使用的角度来看。它们应该使用getGeneratedKeys或使用INSERT ... RETURNINGwith DEFAULT作为密钥,让数据库来处理此事,而Hibernate不必麻烦序列名称或对它们的显式访问。

顺便说一句,如果您将Hibernate与Pg一起使用,则可能还希望为Pg使用oplock触发器,以允许Hibernate的乐观锁定与普通数据库锁定安全地交互。没有它或类似的东西,您的Hibernate更新将倾向于破坏通过其他常规SQL客户端进行的更改。问我我怎么知道。



 类似资料:
  • 问题内容: 我有一个实体,该实体具有必须从序列中设置的NON-ID字段。目前,我获取序列的第一个值,将其存储在客户端,然后根据该值进行计算。 但是,我正在寻找一种“更好”的方法。我实现了一种获取下一个序列值的方法: 但是,这种方式会大大降低性能(〜5000个对象的创建速度降低了3倍-从5740ms到13648ms)。 我试图添加一个“假”实体: 但是,该方法也不起作用(返回的所有ID为0)。 有人

  • 我已经安装了新的数据库,在我的本地序列,并能够看到下一个序列值通过命令提示符。但是,当我试图使用JUnit测试DAO类时,我会得到以下错误。下面的错误声明没有特权...但我可以使用cmnd提示符获取下一个序列值。 错误:

  • 我有一个实体类具有以下主键生成策略 我想知道是否有一种方法可以使用EntityManager向表生成器询问下一个值。

  • 映射 FO:Hibernate:选择marki0_. id作为id3_,marki0_. mark作为marka3_从public.markimarki0_INFO:无法从结果集读取列值:marka3_;无法反序列化SEVERE:org.hibernate.type.序列化异常:无法反序列化org.hibernate.util.串行化Helper.deserialize(串行化Helper.jav

  • 我正在进行shell排序,但无法对列表中的第一个值进行排序。例如如果列表{7,2,6,4,5),则在对列表{7,2,4,5,6}进行排序之后。你们能帮忙吗!公共静态void segmentedInsertionSort(int[]list,int n,int h){int j;

  • 问题内容: Hibernate在创建SessionFactory时抛出此异常: org.hibernate.loader.MultipleBagFetchException:无法同时获取多个包 这是我的测试用例: Parent.java Child.java 这个问题怎么样?我能做什么? 编辑 好的,我的问题是另一个“父”实体在我的父内部,我的真实行为是这样的: Parent.java Anoth