我有gwt应用程序连接到后端的postgres DB,以及一个java类'Judgment'映射数据库中的表'判断',当我试图将判断持久化到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)
我在DB
中有一个SEQUENCE名称'judgements_id_seq'任何人都可以告诉我什么是错的???感谢。
答案 0 :(得分:80)
Hibernate的PostgreSQL方言不是很明亮。它不知道你的每个SERIAL序列,并假设有一个全局数据库范围的序列叫做“hibernate_sequence”它可以使用。
( UPDATE :在指定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 ... RETURNING
和DEFAULT
作为密钥,让数据库处理这个问题,而Hibernate不必在序列名称或显式访问权限上自行解决问题。它们。
答案 1 :(得分:41)
我似乎记得必须使用@GeneratedValue(strategy = GenerationType.IDENTITY)
让Hibernate在PostgreSQL上使用'serial'列。
答案 2 :(得分:11)
您需要使用策略GenerationType.IDENTITY而不是GenerationType.AUTO
设置@GeneratedId列@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "JUD_ID")
private Long _judId;
答案 3 :(得分:8)
我之前有同样的错误,
在数据库CREATE SEQUENCE hibernate_sequence START WITH 1 INCREMENT BY 1 NOCYCLE;
这对我有用,祝你好运〜
答案 4 :(得分:2)
我还想补充一些关于MySQL-to-PostgreSQL迁移的注释:
就我现在所记得的那样,希望这些技巧可以让你免费试听几分钟的试错!
答案 5 :(得分:2)
我认为你已经有了足够的答案,但我得到了完全相同的错误,我的问题是另一个错误。我浪费了一点时间试图解决它。
在我的情况下,问题是Postgres中序列的所有者。因此,如果上述任何解决方案都没有解决您的问题,请检查序列的所有者是否应该拥有权限的用户/角色。
关注示例:
CREATE SEQUENCE seq_abcd
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.seq_abcd OWNER TO USER_APP;
我希望它对任何人都有用。
答案 6 :(得分:0)
我们正在使用的数据库应该在Postgres SQL配置文件的search_path下提及。这可以通过设置search_path和数据库名称来编辑Postgressql配置文件来完成,例如:TESTDB。
在做出上述改变后,它对我有用。
答案 7 :(得分:0)
将GeneratedValue
和GenericGenerator
与native
策略结合使用:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_native")
@GenericGenerator(name = "id_native", strategy = "native")
@Column(name = "id", updatable = false, nullable = false)
private Long id;
我必须创建一个序列调用hibernate_sequence
,因为Hibernate默认会查找这样的序列:
create sequence hibernate_sequence start with 1 increment by 50;
grant usage, select on all sequences in schema public to my_user_name;
答案 8 :(得分:0)
如果使用Postgres,请使用名称“ hibernate_sequence”手动创建序列。它将起作用。
答案 9 :(得分:0)
请使用以下查询并更改您的表:
CREATE SEQUENCE user_id_seq START 1;
ALTER TABLE product.users ALTER COLUMN user_id SET DEFAULT nextval('user_id_seq');
ALTER SEQUENCE users.user_id_seq OWNED BY users.user_id;
并在您的实体类中使用this
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator="user_id_seq")
答案 10 :(得分:0)
对于使用FluentNHibernate(我的版本是2.1.2)的任何人来说,它都是重复的,但这是可行的:
public class UserMap : ClassMap<User>
{
public UserMap()
{
Table("users");
Id(x => x.Id).Column("id").GeneratedBy.SequenceIdentity("users_id_seq");