繁体   English   中英

如何在第二个 Spring 引导中通过只有 ID 的嵌套 JSON

[英]How to pass nested JSON with only ID in the second Spring Boot

我有这个 JSON 来创建一个具有现有帐户的新用户(我只传递属性 accountId):

{
    "account": {
            "accountId":"06xxxx-5fxx-4xxx-xxxx-xxxxxx"
    },
    "userName":"user3",
    "emailAddress":"user3@gmail.com",
  "password":"123",
    "enabled":"1",
    "lastLogin":"2020-07-28"
}

我的用户 model 如下:

public class User implements Serializable {

    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(name = "userId")
    private String userId;

    @JoinColumn(name = "accountId", referencedColumnName = "accountId", nullable = false)
    @ManyToOne
    private Account account;

    @NaturalId
    @Column(name = "userName")
    private String userName;

    @Column(name = "emailAddress")
    private String emailAddress;

    @Column(name = "password")
    private String password;

    @Column(name = "enabled")
    private Integer enabled;

    @Column(name = "lastLogin")
    private String lastLogin;

    @OneToMany(
            mappedBy = "user",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<UserGroupUser> userGroups = new ArrayList<>();

//Constructor, Getters and setters

}

class 帐户是在用户之前创建的第一个实例:

public class Account implements Serializable {

    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(name = "accountId")
    private String accountId;

    @Column(name = "accountName")
    private String accountName;

    @Column(name = "company")
    private String company;

    @Column(name = "address")
    private String address;

    @Column(name = "emailAddress")
    private String emailAddress;

    @Column(name = "dicomId")
    private String dicomId;

    @Column(name = "enabled")
    private Integer enabled;

    @OneToMany (mappedBy = "account",
                cascade = CascadeType.ALL,
                orphanRemoval = true)
    Set<User> users = new HashSet<>();

    @OneToMany (mappedBy = "account",
                cascade = CascadeType.ALL,
                orphanRemoval = true)
    Set<UserGroup> userGroups = new HashSet<>();

    //Constructor, Getters and setters
}

我必须使用 Spring 引导来做到这一点。 请问这些情况下什么是最真实的?

这是我的异常消息,如下所示:

{
  "timestamp": "2020-07-29T08:00:05.608+0000",
  "message": "The given id must not be null!; nested exception is java.lang.IllegalArgumentException: The given id must not be null!",
  "details": "uri=/api/v1/addUser"
}

Spring 引导控制台生成:

2020-07-29 11:38:43.141  INFO 14172 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9898 (http) with context path ''
2020-07-29 11:38:43.144  INFO 14172 --- [  restartedMain] c.p.conexiona.ConexionaApplication       : Started ConexionaApplication in 6.526 seconds (JVM running for 8.967)
2020-07-29 11:38:43.146 DEBUG 14172 --- [  restartedMain] o.s.boot.devtools.restart.Restarter      : Creating new Restarter for thread Thread[main,5,main]
2020-07-29 11:38:43.147 DEBUG 14172 --- [  restartedMain] o.s.boot.devtools.restart.Restarter      : Immediately restarting application
2020-07-29 11:38:43.147 DEBUG 14172 --- [  restartedMain] o.s.boot.devtools.restart.Restarter      : Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@10c515a9
2020-07-29 11:38:43.147 DEBUG 14172 --- [  restartedMain] o.s.boot.devtools.restart.Restarter      : Starting application com.practicas.conexiona.ConexionaApplication with URLs [file:/C:/Users/canro/IdeaProjects/project_example/target/classes/]
2020-07-29 11:38:56.911  INFO 14172 --- [nio-9898-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-07-29 11:38:56.912  INFO 14172 --- [nio-9898-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-07-29 11:38:56.912 DEBUG 14172 --- [nio-9898-exec-1] o.s.web.servlet.DispatcherServlet        : Detected StandardServletMultipartResolver
2020-07-29 11:38:56.920 DEBUG 14172 --- [nio-9898-exec-1] o.s.web.servlet.DispatcherServlet        : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2020-07-29 11:38:56.920  INFO 14172 --- [nio-9898-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 8 ms
2020-07-29 11:38:56.930 DEBUG 14172 --- [nio-9898-exec-1] o.s.web.servlet.DispatcherServlet        : POST "/api/v1/addUser", parameters={}
2020-07-29 11:38:56.933 DEBUG 14172 --- [nio-9898-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.example.rest.UserController#createUser(User)
2020-07-29 11:38:57.030 DEBUG 14172 --- [nio-9898-exec-1] m.m.a.RequestResponseBodyMethodProcessor : Read "application/json;charset=UTF-8" to [com.example.model.User@2802b333]
null
2020-07-29 11:38:57.427 DEBUG 14172 --- [nio-9898-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Using @ExceptionHandler com.example.exception.GlobalExceptionHandler#globleExcpetionHandler(Exception, WebRequest)
2020-07-29 11:38:57.446 DEBUG 14172 --- [nio-9898-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
2020-07-29 11:38:57.447 DEBUG 14172 --- [nio-9898-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [com.example.exception.ErrorDetails@4ddbc615]
2020-07-29 11:38:57.466  WARN 14172 --- [nio-9898-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.dao.InvalidDataAccessApiUsageException: The given id must not be null!; nested exception is java.lang.IllegalArgumentException: The given id must not be null!]
2020-07-29 11:38:57.466 DEBUG 14172 --- [nio-9898-exec-1] o.s.web.servlet.DispatcherServlet        : Completed 500 INTERNAL_SERVER_ERROR

用户控制器:

@RestController
@RequestMapping("/api/v1")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/users")
    public List<User> getAllUsers() {
        return userService.findAllUsers();
    }

    @GetMapping("/users/{id}")
    public ResponseEntity<User> getUserById(
            @PathVariable(value = "id") String userId) throws ResourceNotFoundException {
        User user = userService.findUserById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("user not found on :: "+ userId));
        return ResponseEntity.ok().body(user);
    }

    @PostMapping("/addUser")
    public User createUser(@Valid @RequestBody User user) { return userService.addUser(user); }

    @PutMapping("/users/{id}")
    public ResponseEntity<User> updateUser(
            @PathVariable(value = "id") String userId,
            @Valid @RequestBody User userDetails) throws ResourceNotFoundException {
        User user = userService.findUserById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("user not found on :: "+ userId));

        final User updatedUser = userService.updateUser(userDetails, user);
        if  (updatedUser == null){
            return new ResponseEntity<User>(HttpStatus.EXPECTATION_FAILED);
        } else {
            return ResponseEntity.ok(updatedUser);
        }
    }

    @DeleteMapping("/user/{id}")
    public Map<String, Boolean> deleteUser(
            @PathVariable(value = "id") String userId) throws Exception {
        User user = userService.findUserById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("user not found on :: "+ userId));

        userService.deleteUser(user);
        Map<String, Boolean> response = new HashMap<>();
        response.put("deleted", Boolean.TRUE);
        return response;
    }

}

用户服务:

@Service
public class UserService implements IUserService{
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private AccountRepository accountRepository;

    @Override
    public List<User> findAllUsers() {
        return (List<User>) userRepository.findAll();
    }

    @Override
    public Optional<User> findUserById(String userId){
        return userRepository.findById(userId);
    }

    @Override
    public User addUser(User user){
        User userExisted = userRepository.findById(user.getUserId()).get();
        Account accountExisted = accountRepository.findById(user.getAccount().getAccountId()).get();

        if(userExisted != null || accountExisted == null){
            return null;
        } else {
            user.setAccount(accountExisted);
            return userRepository.save(user);
        }
    }

    @Override
    public User updateUser(User userDetails, User user){
        Account accountExisted = accountRepository.findById(userDetails.getAccount().getAccountId()).get();

        if( accountExisted == null){
            return null;
        } else {
            user.setEmailAddress(userDetails.getEmailAddress());
            user.setUserName(userDetails.getUserName());
            user.setAccount(userDetails.getAccount());
            user.setPassword(userDetails.getPassword());
            user.setAccount(accountExisted);

            return userRepository.save(user);
        }
    }

    @Override
    public void deleteUser (User user){
        userRepository.delete(user);
    }
}

在您的addUser方法中,您正在尝试使用其userId加载用户:

@Override
public User addUser(User user){
    User userExisted = userRepository.findById(user.getUserId()).get();
    // ...
}

虽然从技术上讲这很好,但当您知道user参数尚未持久化因此还没有生成的 id时,它将不起作用。

你应该:

  • 更新您的方法实现以检查user输入是否已经包含userId属性(如果没有,您假设尚未创建用户):

     @Override public User addUser(User user){ User userExisted = null; if (user.getUserId().= null) { userExisted = userRepository.findById(user.getUserId());get(). } //... }
  • 更新您的addUser方法以根据其他唯一谓词(用户名、email 或两者)搜索用户。

请注意,第二个选项将是最合适的选项,并且遵循 RESTful 架构,因为尝试创建具有现有用户 ID 的用户应该已经导致错误(您应该根据您的应用程序需要进行翻译)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM