业务很简单。更新数据一般有以下几种方案
1.数据传给前段时,传所有字段,然后后台直接拿前段的数据进行全字段更新。
2.更新前从DB查询一下,然后往查询的对象上根据业务选择赋值或不赋值,然后更新数据库。
3.根据传来的数据拼SQL更新。
项目是前后端分离的项目,如果采用方案1,每次更新时前端需要写大量赋值代码,比如一个vo有50个字段,我只更新了一个字段,前端会需要传递50个字段给后台controller,冗余了。
如果采用方案2,即我每次针对同一张表 更新不同字段时都需要新写接口?这样太麻烦了。
方案3可以试试,但是写的过程中也有一些问题 。
问题:数据插入/更新时 只插入/更新 指定字段
序列化/反序列化工具 : jackson
vo示例:
public class User extends BaseVO{
private String id;
private String userName;
private String code;
//getter setter ...
}
public class BaseVO{//公共字段
private String createrId;
private String updaterId;
private Date createDate;
private Date updateDate;
//getter setter ...
}
Controller示例:
@PutMapping(value = "/update")
public void update(@RequestBody User user) {
Json json = new Json();
try {
user.setUpdaterId(this.getRequest().getUserId);//取当前登录用户id
userService.update(user);
json.setResult(true);
} catch (Exception e) {
printErrorLog(json, e, "更新失败");
}
writeJson(json);
}
//Service和DAO都是一样的
Service:
public void update(User user){
// ...校验
userDao.update(user);
}
DAO:
public void update(User user){
Single.update(user);//Single 为自定义的持久层 基于jdbcTemplate 构造sql时 默认更新所有字段
// Single.update(user, new String[]{"userName"}); // 可传入自定义字段列表 只更新 userName字段
}
Single:
public void update(User user,String[] fieldNames){
//构造sql
String [] fields = null;
if(fieldNames != null && fieldNames.length > 0){
fields =fieldNames; // 指定字段
}else{
fields = getAll();// 取vo所有字段
}
//根据fields构造sql并执行 拼接sql 只更新指定的字段
...
}
前端json字符串示例:case1 : {"id":"123456","userName":"zhangsan"}
case2 : {"id":"123456","code":"001"}
case1时,传入controller层的user 字段{id=123456 userName=zhangsan code=null 公共字段=null} ;
case2时,传入controller层的user 字段{id=123456 userName=null code=001 公共字段=null} ;
直接调service更新 会把不传递的字段 置空。
那么问题来了,在service和dao不变的情况下如何实现只更新前端传递的字段呢?
在BaseVO增加 String[] saveFields 字段,在由json字符串反序列化成vo对象时 ,将前端传递的字段列表作为String数组 设置到 vo的 String[] saveFields 中
在Single类 update方法中 fields 取 vo.getSaveFields();
如何在反序列化时 给 vo 的字段 saveFields 设值?