[英]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.