You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot R2DBC中POST请求自动生成实体ID的方法求助

问题描述

我开发了一个Spring Boot/R2DBC应用,相关代码及遇到的问题如下:

控制器代码

@PostMapping("/add")
public ResponseEntity<String> create(@RequestBody NotificationEntity e) {
    notificationDAO.save(e).subscribe();
    return new ResponseEntity<>(HttpStatus.OK);
}

Repository代码

@Repository
public interface NotificationDAO extends ReactiveCrudRepository<NotificationEntity, Long> {

}

实体类代码

@Data
@ToString
@Table(name = "notification")
public class NotificationEntity {

@Column
@Id
private Long id;

@Column(value = "content_pl")
private String contentPL;

@Column(value = "content_en")
private String contentEN;

@Column(value = "event_date")
private LocalDateTime eventDate;

@Column
private LocalDateTime seen;

@Column(value = "application_id")
private Integer applicationId;

@Column(value = "recipient_id")
private Integer recipientId;

@Column(value = "type_id")
private Integer typeId;

@Column(value = "document_id")
private Integer documentId;

@Column(value = "kom_id")
private Integer komId;

@Column(value = "koz_id")
private Integer kozId;

@Column(value = "kof_id")
private Integer kofId;

@Column(value = "control_id")
private Integer controlId;
}

PostgreSQL表结构

CREATE TABLE public.notification (
    id int8 NOT NULL,
    content_en text NULL,
    content_pl text NULL,
    event_date timestamp NULL,
    seen timestamp NULL,
    application_id int8 NULL,
    recipient_id int8 NULL,
    type_id int8 NULL,
    document_id int8 NULL,
    kom_id int8 NULL,
    koz_id int8 NULL,
    kof_id int8 NULL,
    control_id int8 NULL,
    CONSTRAINT notification_pkey PRIMARY KEY (id),
    CONSTRAINT fk3gh0fu4xhghdgd62lm6mljcaf FOREIGN KEY (kom_id) REFERENCES public.merit_evaluation_card(id),
    CONSTRAINT fk_control_id FOREIGN KEY (control_id) REFERENCES public.application_control(id),
    CONSTRAINT fk_kof_id FOREIGN KEY (kof_id) REFERENCES public.formal_evaluation_card(id),
    CONSTRAINT fk_kom_id FOREIGN KEY (kom_id) REFERENCES public.merit_evaluation_card(id),
    CONSTRAINT fk_koz_id FOREIGN KEY (koz_id) REFERENCES public.merit_team_evaluation_card(id),
    CONSTRAINT fkdolhc4dbxvvovwo0924ifbrxn FOREIGN KEY (koz_id) REFERENCES public.merit_team_evaluation_card(id),
    CONSTRAINT fkigjeg33g1pae9aqliuepdxnpy FOREIGN KEY (document_id) REFERENCES public."document"(id),
    CONSTRAINT fkk8h5styb6x923o4kkokn5k1a7 FOREIGN KEY (application_id) REFERENCES public.application(id),
    CONSTRAINT fkl7oja3n6j1vkasuqmux4isnk8 FOREIGN KEY (type_id) REFERENCES public.metrics_type(id),
    CONSTRAINT fkmlumq0ssiy6k7cklmg337k03a FOREIGN KEY (kof_id) REFERENCES public.formal_evaluation_card(id),
    CONSTRAINT fkmmav4veuakqbfiuctechf7qx4 FOREIGN KEY (recipient_id) REFERENCES public.app_user(id)
);
CREATE INDEX notification_application_id_idx ON public.notification USING btree (application_id);
CREATE INDEX notification_control_id_idx ON public.notification USING btree (control_id);
CREATE INDEX notification_document_id_idx ON public.notification USING btree (document_id);
CREATE INDEX notification_kof_id_idx ON public.notification USING btree (kof_id);
CREATE INDEX notification_kom_id_idx ON public.notification USING btree (kom_id);
CREATE INDEX notification_koz_id_idx ON public.notification USING btree (koz_id);
CREATE INDEX notification_recipient_id_idx ON public.notification USING btree (recipient_id);
CREATE INDEX notification_type_id_idx ON public.notification USING btree (type_id);

触发的错误

当向/api/add接口POST不含id字段的JSON数据时:

{
    "contentPL": "Wnifgh",
    "contentEN": "Apfgh",
    "eventDate": "2018-04-27T17:39:18.622",
    "seen": "2018-05-02T08:46:51.892",
    "applicationId": 7388,
    "recipientId": 1,
    "typeId": 2,
    "documentId": null,
    "komId": null,
    "kozId": null,
    "kofId": null,
    "controlId": null
}

抛出以下错误:

Caused by: io.r2dbc.postgresql.ExceptionFactory$PostgresqlDataIntegrityViolationException: null value in column "id" of relation "notification" violates not-null constraint

之前在JPA中可以用@GeneratedValue实现自动生成ID,请问在R2DBC中怎么实现相同效果?

解决方案

要在R2DBC中实现自动生成ID,需要同时修改数据库表结构和实体类注解,步骤如下:

1. 修改PostgreSQL表结构,设置ID自增

PostgreSQL 10+推荐使用标准的GENERATED AS IDENTITY语法实现自增主键,执行以下SQL修改现有表:

ALTER TABLE public.notification ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY;

如果是新建表,可直接将id字段定义为:

id int8 GENERATED ALWAYS AS IDENTITY NOT NULL,

2. 修改实体类,添加自动生成ID注解

在R2DBC中,需给@Id字段添加@GeneratedValue注解并指定策略,修改实体类的id字段:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

这里的GenerationType.IDENTITY与数据库的自增策略匹配,R2DBC会自动将数据库生成的ID回填到实体对象中。

3. 优化控制器代码(可选但推荐)

原控制器直接调用subscribe()会忽略保存过程中的错误,建议改为返回Mono,让Spring WebFlux处理异步流程并捕获异常:

@PostMapping("/add")
public Mono<ResponseEntity<String>> create(@RequestBody NotificationEntity e) {
    return notificationDAO.save(e)
            .map(saved -> new ResponseEntity<>("创建成功", HttpStatus.OK))
            .onErrorResume(ex -> Mono.just(new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST)));
}

完成以上修改后,POST不含id的JSON数据时,数据库会自动生成ID值,不会再触发非空约束错误。

内容的提问来源于stack exchange,提问作者mtmx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 03:44:56