myBatis: how to return pojo with insert?

I have a simple POJO:

@Data
@NoArgsConstructor
public class User {

    private Long id;
    private String username;
    private String password;

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

I have mapper, saving this POJO and returning ID.

@Insert("insert into users(username, password) values(#{user.username}, #{user.password})")
@Options(useGeneratedKeys = true, keyProperty = "id")
Long save(@Param("user") User user);

Than, service receive entity by this ID:

@Override
public User save(User user) {
    return Optional.ofNullable(
            mapper.findById(
                    Optional.ofNullable(mapper.save(user))
                            .orElseThrow(() -> new EntityNotSavedException("Не удалось сохранить: " + user)))
    )
            .orElseThrow(() -> new EntityNotSavedException("Не удалось сохранить: " + user));
}

In this case, we have one request to insert entity & second - to select it from id. Costs too much.

How to return entity after inserting in one request?

Upvotes: 0

Views: 884

Answers (1)

ave
ave

Reputation: 3594

You don't need to perform the select.
It's a common misunderstanding, but @Insert method returns the number of updated rows, not the generated key (this is how the underlying JDBC API works).
As you specified keyProperty="id", the generated key is set to id property of the passed User parameter.

Note that you should specify keyColumn as well.
It's required since version 3.5.0.

If your service method has to return a User, it may look something like this.

@Override
public User save(User user) {
  if (mapper.save(user) != 1) {
    // this may not happen.
    // an exception will be thrown if insert failed.
  }
  return user;
}

Usually, the service method just performs INSERT and the caller keeps using the original User instance for later operation.

The service method:

@Override
public void save(User user) {
  mapper.save(user);
}

The class calling the service method would look like...

User user = new User("John", "xyz");
service.save(user);
model.addAttribute("user", user);
...

Upvotes: 3

Related Questions