所以我所拥有的是一个弹簧控制器:
@Controller
@RequestMapping("/user")
public class UserController() {
@RequestMapping(value = "/edit/{id}", method = RequestMethod.PUT)
public @ResponseBody HTTPResponseDTO edit(@RequestBody String data, @PathVariable long id) {
// marshall data String to User entity
ObjectMapper mapper = new ObjectMapper();
User marshaledUser = mapper.readValue(data, User.class);
User databaseUser = session.get(id, User.class);
//hibernate things to save
...
// session.save(user);
}
数据字符串采用以下json格式:
{"name":"value1",
"email":"value2",
"note":"value3"}
responseDTO看似简单:
{"result":"success"}
当客户端传入数据json时,它只会传入正在编辑的值,例如:
{"email":"value2"}
在这种情况下,其他非提供的字段将被视为null。
然而"注意"是一个可以为空的字段,用户可以清除" note" field - 在我目前的设计中,当它这样做时,它将是:
{"note":null}
问题1: 所以这就是我的困境:如何判断用户是否有意将其设置为null,或者只是因为它没有从数据字符串传入而为空?
问题2: 当控制器正在接收数据字符串时,我将有一个来自此数据的实体,然后我将通过id查询数据库以获取现有的User对象。合并这两个对象的最佳做法是什么?查找marshaledUser中存在哪些字段并将其设置为databaseUser看起来像很多重复的工作:
if (marshaledUser.name != null) {
databaseUser.name = marshaledUser.name;
}
if (marshaledUser.email != null) {
databaseUser.email = marshaledUser.email;
}
if (marshaledUser.note != null) { // refer to question 1...
databaseUser.note = marshaledUser.note;
}
一个对象可以缓和超过5个字段 - 如果几乎相同的事情看起来不值得5,那么..处理这个问题的最佳做法是什么?
答案 0 :(得分:2)
问题1:所以这就是我的困境:如何判断用户是否有意将其设置为null,或者只是因为它没有从数据字符串传入而为空?
你做不到。所以,要么改变你的方法,要么总是传递一个完整的用户(这就是我要做的事情),而不仅仅是几个字段,或者将JSON解组为Map(或JsonObject)。如果密钥存在但具有空值,则传递的值为null。如果密钥不存在,则表示尚未通过。
问题2:当控制器正在接收数据字符串时,我将有一个来自此数据的实体,然后我将通过id查询数据库以获取现有的User对象。合并这两个对象的最佳做法是什么?
与问题1相同。如果客户端传递完整的User对象而不是仅传递几个字段,那将会简单得多。该方法看起来像
@RequestMapping(value = "/edit/{id}", method = RequestMethod.PUT)
public @ResponseBody HTTPResponseDTO edit(@RequestBody User user, @PathVariable long id)
user.setId(id);
session.merge(user);
}
或者至少,您只需将传递过的用户的每个字段复制到持久用户,而不用关心是否已经发送过。
此外,返回包含result = success
的HttpResponseDTO是多余的。如果方法正常完成,它将返回200 - OK HTTP状态。如果没有,那么您应该返回另一个HTTP状态代码。
答案 1 :(得分:0)
我认为1方法是从数据库中读取目标对象并将其转换为json。然后使用描述here
的技术合并您的请求json