Spring使用更新而不是保存功能

5

我想编写一个基于R2DBC的小型反应式后端,但遇到了一些我不太理解的问题。我不知道为什么Spring试图更新一个条目,而不是将其保存到数据库中。

我的用户模型:

@Table("user")
@NoArgsConstructor
@Data
public class User {

    @Id
    private String id;

    private String username;
    private String password;

    public User(String id,String username,String password){
        this.id = id;
        this.username = username;
        this.password=password;
    }

我的控制器:

@RestController
    public class UserController {

`   private final UserRepository userRepository`;

    @Autowired
    public UserController(UserRepository userRepository){

        this.userRepository = userRepository;
    }

    @PostMapping("/create")
        public Mono<User> createUser(@RequestBody User user){
            return userRepository.save(user);
        }   

当我向此端点发送一个类似于以下输入的POST请求时:
{ "id" : "re", "username" : "ehmmidk", "password" : "dsadsadsadsa" }
即使我的数据库中没有条目,它也会执行更新而不是保存操作。
我的模式如下:
CREATE TABLE user (
   id VARCHAR(255) NOT NULL ,
   username VARCHAR(255) NOT NULL,
   password VARCHAR(255) NOT NULL,


   PRIMARY KEY (id),
   UNIQUE(username)
);

你能否更新你的帖子,包括存储库代码?如果你正在使用JPA,则必须在实体类中声明Entity注释。 - Manuel Jordan
6个回答

8
可能的原因是您正在发布一个带有预填充id的实体:
{ "id" : "re", "username" : "ehmmidk", "password" : "dsadsadsadsa" }

我发现如果声明的实体实现了“Persistable”接口,则必须实现“isNew()”方法,该方法定义了“repository.save()”的行为——它是否会触发“INSERT”或“UPDATE”。
我看到在您的情况下,您没有实现“Persistable”,但也许默认行为是……
boolean isNew() { return id == null; }

这可能意味着在您的情况下,Spring Data R2DBC认为该实体不是新的,因此执行了一次UPDATE操作。

不过这只是我的猜测。


1
你需要添加 @GeneratedValue(strategy = GenerationType.IDENTITY)。Spring 的 Crud 存储库没有创建和更新方法,而只有保存方法(参见 saveAndFlush)。它通过 @id 处理创建和更新,所以如果 id 字段存在,则执行更新。

不工作 不工作 - Andres Camilo Sierra Hormiga

1

请查看我为即将到来的Spring Boot 2.4、Spring 5.3和Spring Data R2DBC 1.2创建的新示例

在此示例中,我使用了Postgres。它使用ApplicationRunner将一些示例数据初始化到数据库中。

当保存User实体(而不是Persistable)时,您需要将标识符设置为非空值,Spring Data R2DBC将使用它来检查实体是否为新的。如果实体是Persistable,则将使用isNew方法来确定实体是否为新的

但是,您可以使用R2dbc DatabaseClient手动插入数据以按预期执行SQL查询,请在这里查看我的DatabaseClient示例(但我在此处使用了由数据库生成的id)。


1

fyrkov的回答是正确的:https://dev59.com/1b3pa4cB1Zd3GeqPdGJm#64170679

然而,我发现当您不使用数据库生成的id值时,使用乐观锁定是让Spring Data R2DBC正常工作的另一种方法。例如,将@Version注释字段添加到您的JPA实体中。

@Version private Long version;

我不确定为什么,但它确实起作用了。


-4

看起来您忘记在实体类User上使用注解@Entity


2
R2DBC 中没有注释实体,但我认为这不是问题所在。 - Yasin Eraslan

-4
应该将@Entity和@GeneratedValue添加到您的pojo中。
@GeneratedValue将有助于定义主键值生成的策略(如Identify/Sequence)。
如果可能,请在控制台中打印出更新SQL查询以进行进一步分析。

1
我正在使用R2DBC,我没有注入JPA依赖项,我需要注入那个依赖项吗? - Yasin Eraslan
不需要注入依赖项。如果您不想更新该记录,请在JSON中不提供ID字段,然后再尝试处理它。 - suseelkumar annamraju

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接