春季执行更新而不是保存

huangapple go评论73阅读模式
英文:

Spring does Update instead of save

问题

我正在尝试使用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)
);
英文:

I am trying to code a little reactive backend with R2DBC and run into a thing I do not really understand. I dont know why but Spring is trying to update an entry instead of saving it to the database.

My User Model:

@Table(&quot;user&quot;)
@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;
    }

My Controller:

@RestController
    public class UserController {

`   private final UserRepository userRepository`;

    @Autowired
    public UserController(UserRepository userRepository){

        this.userRepository = userRepository;
    }

    @PostMapping(&quot;/create&quot;)
        public Mono&lt;User&gt; createUser(@RequestBody User user){
            return userRepository.save(user);
        }   

When I sent a POST request to this endpoint with input like this for example:

{
"id" : "re",
"username" : "ehmmidk",
"password" : "dsadsadsadsa"
}

it does an update insted of a save even when there is no entries in my database.

My schema looks like this:

CREATE TABLE user (
   id VARCHAR(255) NOT NULL ,
   username VARCHAR(255) NOT NULL,
   password VARCHAR(255) NOT NULL,


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

答案1

得分: 6

原因可能是您正在发布一个带有预填充 id 的实体:

{ "id" : "re", "username" : "ehmmidk", "password" : "dsadsadsadsa" }

我注意到的是,如果一个声明的实体正在实现 Persistable 接口,它必须实现 isNew() 方法,该方法定义了 repository.save() 的行为 - 它是否会触发 INSERTUPDATE

我看到在您的情况下,您没有实现 Persistable,但可能默认行为是:

boolean isNew() { return id == null; }

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

然而,这只是我的猜测。

英文:

The reason could be that you are posting an entity with the pre-filled id:

{ &quot;id&quot; : &quot;re&quot;, &quot;username&quot; : &quot;ehmmidk&quot;, &quot;password&quot; : &quot;dsadsadsadsa&quot; }

What I spotted is that if a declared entity is implementing Persistable interface it must implement isNew() method which defines the behavior of repository.save() - will it fire an INSERT or an UPDATE.

I see that in your case you do not implement Persistable but maybe then the default behavior is

boolean isNew() { return id == null; }

That might mean in your case that the entity is considered as not new by Spring data r2dbc and that's why it makes an UPDATE.

However this is only my guess.

答案2

得分: 1

你需要添加@GeneratedValue(strategy = GenerationType.IDENTITY)。Spring的Crud repositories没有创建和更新方法,只有save方法(还可以看看saveAndFlush方法)。它通过@id处理创建和更新操作,因此如果id字段存在,它会执行更新。

英文:

You need to ad the @GeneratedValue(strategy = GenerationType.IDENTITY). Spring's Crud repositories do not have create and update methods but only save (see also saveAndFlush). It handles creation and update through @id, so if the id field is present it performs an update

答案3

得分: 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)。

英文:

Check my new example for upcoming Spring Boot 2.4, Spring 5.3, and Spring Data R2DBC 1.2.

I am using Postgres in this example. It used ApplicationRunner to initialize some sample data into the database.

You set the identifier a non-null value when saving the User entity(not a Persistable), Spring Data R2DBC uses it to check if the entity is new. If the entity is a Persistable, it will use the isNew method to determine if the entity is new.

However, you can insert data manually using R2dbc DatabaseClient to execute SQL queries as expected, check my DatabaseClient example here(but I used a database generated id here).

答案4

得分: 1

fyrkov 的回答是正确的:https://stackoverflow.com/a/64170679/928550

然而,我发现在不使用数据库生成的 id 值时,使用乐观锁定(Optimistic locking)是让 Spring Data R2DBC 做正确操作的另一种方式。

例如,在你的 JPA 实体中添加一个带有 @Version 注解的字段。

@Version private Long version;

我不太确定为什么,但它有效。

英文:

The answer by fyrkov is correct: https://stackoverflow.com/a/64170679/928550

I have however discovered that using Optimistic locking is another way of getting Spring Data R2DBC to do the right thing when you are not using database generated id values.

eg. Add a @Version annotated fields to you JPA entities.

> @Version private Long version;

I'm not exactly sure why, but for it worked.

答案5

得分: -4

似乎你忘记为你的实体类 User 使用注解 @Entity

英文:

It seems like you forgot to use annotation @Entity for your entity class User

答案6

得分: -4

@Entity和@GeneratedValue应该添加到您的POJO中。

@GeneratedValue将有助于定义主键值生成的策略(如标识/序列)。

如果可能的话,请在控制台中提供您的更新SQL查询以供进一步分析。

英文:

@Entity & @GeneratedValue should be added to your pojo.

@GeneratedValue will help to define the strategy(like Identify/Sequence) for primary key value generation.

If possible provide your update sql query printed in console for further analysis.

huangapple
  • 本文由 发表于 2020年9月23日 22:56:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/64030718.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定