后端为SSM框架,前端采用Layui,相关简介可参考之前的博客:JavaWeb后端开发框架SSM+前端框架Layui简介
1、初始数据表格
2、修改内容:
将“现在地址”一栏中的“南京”修改为“北京”:
3、修改后:
历史变更记录的表格中包含的字段为:(护理机构)名称、修改时间、变更字段名称、变更前内容、变更后内容,以及一些其它自己设定的内容
本次博客仅专注于后端开发,前端内容使用框架(如:数据表格的显示、两个Tab的显示与切换等等)。
在上一节中,采用的“修改信息”页面是使用Layui表单进行设计的,当触发“submit”事件后,使用AJAX传递方式将表单内容传递至后端。
layui表单的设计及提交可参考博客: 用layui实现表单提交(包含图片)
<script>
layui.use('form', function(){
var form = layui.form;
//submit是button的type;handin是自定义的按键id
form.on('submit(handin)', function(data){
console.log("开始提交");
console.log(data.field); //前端调试,查看传递的数据
$.ajax({
url:'/department/updateDepartment', //连接到后端的controller层
method:'POST', //传递方式
data:data.field, //传递的数据
dataType:'JSON', //数据采用Json类型
//事件触发成功后返回res值,并进入以下自定义函数
success:function(res){
console.log("res.msg:"+res.msg);
if(res.msg=="ok"){ //controller层的返回值
console.log("成功提交"+data.field);
//提交成功后刷新页面
layer.msg("提交成功",{icon: 1, time: 1500},function() {location.reload();});
}else{
console.log("请确保“结算代码”输入正确"+data.field);
layer.msg("请确保“结算代码”输入正确",{ icon: 5,anim: 6,offset: "auto"});
}
},
error:function (data) {
console.log("提交失败",data);
}
});
return false;
})
})
此时页面的控制台资源中可以查看到前端传递的数据(即data.field),如下图:
Controller层接收数据
@RequestMapping(value = "/updateDepartment", method = RequestMethod.POST,produces={"application/json;charset=UTF-8"})
@ResponseBody
public String updateDepartment(Department department, HttpSession session) {
//Department为在Model中定义的类,department变量接收前端传来的数据
try {
System.out.println("开始更新");
//进入service层
String abc=departmentService.updateDepartment(department, session);
System.out.println("controller层返回:"+abc);
if(abc=="ok"){
return "{\"msg\":\"ok\"}";
}else{
return "{\"msg\":\"error\"}";
}
} catch (Exception e) {
e.printStackTrace();
logger.error("更新异常!", e);
return "操作异常,请您稍后再试";
}
}
public interface DepartmentService {
// 申明函数
String updateDepartment(Department department, HttpSession session);
}
在该层中定义updateDepartment的具体函数方法。
历史变更记录功能需要解决的主要问题在于:
在新的表单提交后,后端只是接收了数据,还没有更改数据,因此原来表格中的内容即原始信息。
那么,要怎么找到这一条修改前的原始信息呢?通常来说,在设计数据库表时,会默认将 id 作为整个表格中的主键,即相当于是一个唯一标识码,因此可通过前端传来的数据的 id 来找到原始数据的内容。在找到原始信息后,将数据存入HashMap中。
if (department.getId() != null) {
// 根据ID找到修改前的数据
System.out.println("service层:department的ID:"+department.getId());
Department departmentInfobyID=departmentDao.findDepartmentInfobyID(department.getId());
System.out.println("service层:存在此机构");
// 将旧数据存入HashMap
Map<String,Object> oldDepartment = new HashMap<String,Object>();
//此处仅列举几个变量为例
oldDepartment.put("department_name", departmentInfobyID.getDepartment_name());
oldDepartment.put("department_phone_number", departmentInfobyID.getDepartment_phone_number());
oldDepartment.put("department_address", departmentInfobyID.getDepartment_address());
oldDepartment.put("department_settlement_scope", departmentInfobyID.getDepartment_settlement_code());
oldDepartment.put("department_first_settle_date", departmentInfobyID.getDepartment_first_settle_date());
System.out.println("service层:旧的数据:oldDepartment:"+oldDepartment);
}
此处涉及到findDepartmentInfobyID函数,需先在Dao层中定义:
/** 查询/根据id
* @param id
*/
Department findDepartmentInfobyID(@Param("id") Integer id);
并在mapper层定义相同函数名称的方法:
<!--根据ID查询信息-->
<select id="findDepartmentInfobyID" resultType="Model.Department">
select * from db_chx_department
where id = #{id}
</select>
修改后的数据即刚传输进来的数据,同样将其存入HashMap中。
// 将新数据存入HashMap
Map<String,Object> newDepartment = new HashMap<String,Object>();
newDepartment.put("department_name", department.getDepartment_name());
newDepartment.put("department_phone_number", department.getDepartment_phone_number());
newDepartment.put("department_address", department.getDepartment_address());
newDepartment.put("department_settlement_scope", department.getDepartment_settlement_code());
newDepartment.put("department_first_settle_date", department.getDepartment_first_settle_date());
System.out.println("service层:新的数据:newDepartment::"+newDepartment);
// 记录修改时间
Date date = new Date();
Timestamp timestamp = new Timestamp(date.getTime());
departmentInfobyID.setDepartment_change_time(timestamp);
System.out.println("修改时间:"+departmentInfobyID.getDepartment_change_time());
遍历oldDepartment中的每一个键值对,比较新旧表在相同键时的值是否一致,若不一致,则建立新表以存储历史变更信息,若一致则不用存储。
// 遍历 oldDepartment 中的每一个键值对
for(Map.Entry<String,Object>entry:oldDepartment.entrySet()){
// 获取当前遍历到的键
String keyContent=entry.getKey();
System.out.println("获取的key值:"+keyContent);
// 获取当前键的 value 值(新+旧)
// 判断当前键的值是否为空,将值存入oldValue
Object oldValue = entry.getValue()==null?"":entry.getValue();
// 根据当前键,查找到新表对应键的数据:newDepartment.get(entry.getKey()),
// 并判断其值是否为空,存入newValue
Object newValue = newDepartment.get(entry.getKey())==null?"":newDepartment.get(entry.getKey()); //
System.out.println("比较循环前的数据(旧):"+oldValue);
System.out.println("比较循环前的数据(新):"+newValue);
// 比较:如果二者value不同
if(!oldValue.equals(newValue)){
System.out.println("不同");
// 建立新表,用于存储变更信息
Map<String,Object> insertInfo = new HashMap<String,Object>();
// 根据当前键,设置对应的中文名称,用于后期显示“变更字段名称“
switch (keyContent){
case "department_name": insertInfo.put("department_changed_title","机构名称");break;
case "department_phone_number": insertInfo.put("department_changed_title","联系电话");break;
case "department_address":insertInfo.put("department_changed_title","机构地址");break;
case "department_settlement_scope":insertInfo.put("department_changed_title","结算范围");break;
case "department_first_settle_date":insertInfo.put("department_changed_title","首次可结算日期");break;
}
// 在新建表中添加需要记录下的键值对,如:变更字段名称、变更前后信息、变更时间等
insertInfo.put("department_name", department.getDepartment_name());
insertInfo.put("department_settlement_code", department.getDepartment_settlement_code());
insertInfo.put("department_change_time", department.getDepartment_change_time());
insertInfo.put("department_new_content", newValue);
insertInfo.put("department_history_content", oldValue);
System.out.println("变更后的表:"+insertInfo);
// 以哈希表形式传入更改后的数据
System.out.println("进入dao层:InsertHistoryChange");
this.departmentDao.InsertHistoryChange(insertInfo);
}else{
// 若value相同,则不传
System.out.println("相同");
}
// 更新原表中的数据
this.departmentDao.updateById(department);
System.out.println("update成功(Impl)");
}
return "ok"; //愚蠢的返回方式
控制台输出变更后的表信息,由于只更改了一个内容,故而只输出了一条信息;若变更多个内容,则会显示多条信息。
在Dao层定义函数,并在mapper层定义方法:
1)将变更信息插入历史变更记录表中
<!--历史变更-->
<insert id="InsertHistoryChange" useGeneratedKeys="true" parameterType="java.util.HashMap">
insert into db_chx_department_history_change
(department_name,department_settlement_code,department_change_time,
department_changed_title,department_new_content,department_history_content)
values
(#{department_name},#{department_settlement_code},#{department_change_time},
#{department_changed_title},#{department_new_content},#{department_history_content})
</insert>
2)更新旧表
<update id="updateById" parameterType="Model.Department">
update db_chx_department
<set>
<if test="department_name != null"> department_name = #{department_name},
<if test="department_phone_number != null">department_phone_number = #{department_phone_number},
<if test="department_address != null">department_address = #{department_address},
<if test="department_settlement_scope != null">department_settlement_scope = #{department_settlement_scope},
<if test="department_settlement_code != null"> department_settlement_code = #{department_settlement_code}
</set>
where id = #{id}
</update>
以上即完成了整个历史变更功能。
该代码问题在于:在记录修改前后的信息、以及根据键来设置中文名称时,需要逐条罗列数据库表的字段,使代码较为冗长…等一个解决的好方法…
阿巴阿巴阿巴…小萌新报道…如有错误,欢迎指正…