【问题标题】:Use postgres table sequence instead of sharing hibernate_sequence使用 postgres 表序列而不是共享 hibernate_sequence
【发布时间】:2019-11-29 01:47:30
【问题描述】:

当我对表格做任何事情时,它总是显示错误:

Hibernate: select nextval ('hibernate_sequence')
2019-07-20 16:15:44.877  WARN 58376 --- [nio-9000-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 42P01
2019-07-20 16:15:44.877 ERROR 58376 --- [nio-9000-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: relation "hibernate_sequence" does not exist

我不想使用hibernate_sequence在表之间共享id序列,但想为每个表定义id seq并分别使用。

我使用Spring Boot 2.1.6.RELEASE、Spring Data JPA(Hibernate 5.3.10.Final)和Postgres 11.2,并定义了BigSerial类型的id字段,希望在各个实体中使用每个表的id序列类。

演示代码库在这里:https://github.com/Redogame/share_hibernate_sequence

创建用户表(使用身份作为表名,因为用户是 Postgres 保留关键字)。 通过定义bigserial类型的id,Postgres会自动创建一个identity_id_seq,我验证identity_id_seq已经创建成功了。

create table identity
(
    id                  bigserial    not null
        constraint identity_pkey
            primary key,
    name                varchar(255) not null
        constraint identity_name_key
            unique
        constraint identity_name_check
            check ((name)::text <> ''::text),
    created_date        timestamp    not null,
    created_by_id       bigint       not null
        constraint identity_identity_id_fk
            references identity,
    last_modified_date  timestamp    not null,
    last_modified_by_id bigint       not null
        constraint identity_identity_id_fk_2
            references identity,
    version             bigint       not null
);

指定一个序列生成器来使用这个id序列:

@Table(name = "identity")
public class UserEntity extends Auditable<Long> {
    @Id
    @SequenceGenerator(name="identity_id_seq", sequenceName = "identity_id_seq", initialValue=1, allocationSize=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="identity_id_seq")
    private Long id;

但它不起作用。我也试过配置spring.jpa.hibernate.use-new-id-generator-mappingsspring.jpa.properties.hibernate.id.new_generator_mappings,还是不行。

spring:
  jpa:
    hibernate:
      use-new-id-generator-mappings: false
    properties:
      hibernate:
        id:
          new_generator_mappings: false

我希望不要使用hibernate_sequence,即:不要在任何SQL语句之前/之后执行select nextval('hibernate_sequence')。

【问题讨论】:

  • 尝试手动创建一个序列,然后在映射文件中使用它。看它有效。然后我们就可以消除这个问题了。
  • @dassum 你想教我怎么做吗?请尝试在上面的 GitHub 存储库中更正我的源代码。
  • 我已经发布了答案。如果解决了问题,请批准

标签: postgresql java-8 spring-data-jpa hibernate-5.x


【解决方案1】:

试试下面的步骤

  1. 如果不存在则创建序列 manual_seq;

  2. 更改创建表脚本

    create table identity
    (
        id  integer NOT NULL DEFAULT nextval('manual_seq'::regclass),
        name                varchar(255) not null
            constraint identity_name_key
                unique
            constraint identity_name_check
                check ((name)::text <> ''::text),
        created_date        timestamp    not null,
        created_by_id       bigint       not null,
        last_modified_date  timestamp    not null,
        last_modified_by_id bigint       not null,
        version             bigint       not null,
        CONSTRAINT manual_seq_pkey PRIMARY KEY (id)
    );

出于测试目的,我删除了外键约束。

  1. 更新实体映射
    @Entity
    @Table(name = "identity")
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class UserEntity extends Auditable<Long> {
        @Id
        @SequenceGenerator(name="manual-seq", sequenceName = "manual_seq",allocationSize = 1)
        @GeneratedValue(generator="manual-seq")
        private Long id;

        @Basic
        @Column(name = "name", nullable = false)
        private String name;
@MappedSuperclass
@JsonIgnoreProperties({"new", "createdDate", "createdById", "lastModifiedDate", "lastModifiedById", "version"})
abstract class Auditable<PK extends Serializable>{

    @NotAudited
    @CreatedDate
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdDate;

    @NotAudited
    @CreatedBy
    private Long createdById;

    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastModifiedDate;

    @LastModifiedBy
    private Long lastModifiedById;

    @NotAudited
    @Version
    private Long version;

恢复 spring.jpa.hibernate.use-new-id-generator-mappings

问题在于扩展 AbstractPersistable,因为没有使用哪个数据库序列。另外,请注意,出于测试目的,我已删除审核。

【讨论】:

  • 不起作用。最后它仍然使用 hibernate_sequence 。 ``` Hibernate: select userentity0_.id as id1_0_0_, ... Hibernate: select nextval ('identity_id_seq') Hibernate: insert into identity (created_by_id, created_date, last_modified_by_id, last_modified_date, version, name, id) 值 (?, ?, ?, ?, ?, ?, ?) Hibernate: select nextval ('hibernate_sequence') ``` 你用你的修改测试了吗?您可以在此处粘贴您的差异或创建拉取请求吗?
  • @user2606091 我已经用你的代码测试过了。更改在抽象类 Auditable 中。不要扩展 AbstractPersistable。
【解决方案2】:

同样的问题也发生在我身上。我明确设置了spring.jpa.properties.hibernate.id.new_generator_mappings=false,但select nextval ('hibernate_sequence') 仍然由Hibernate 运行。

我发现当我们使用@GeneratedValue注解而不设置策略时,它默认为AUTO,这意味着Hibernate会尝试使用hibernate_sequence生成ID值,然后它会失败,因为它没有' t 存在于数据库中。

所以,我创建了@GeneratedValue (strategy = GenerationType.IDENTITY) 并再次尝试。在这种情况下,ID 值是由我在数据库中的标识列(自动递增的主键)而不是由hibernate_sequence 生成的。

create table users (id serial not null, name varchar(250), primary key (id));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-09
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多