aisell_CRUD

一.删除功能

	1.简要步骤
	(1)先拿到要删除的哪一条数据
	(2)如果没有选择某条数据就在点击删除,弹出消息框告知要选择数据
	(3)如果选择了数据,弹出消息框提示是否删除
	(4)确认删除后。拿到前台的id值到后台进行删除操作
					删除成功--->刷新页面
					删除失败--->弹出消息框提示
	(5)写一个后台返回到前台值的类JsonResult.java。(目的就是确定好返回的值的类型)
	2.代码部分
	(1).后台返回前台的值的类型的类
 		// 后台返回到前台的值。以后都会使用到{success:true,msg:xxxx}这样的
		public class JsonResult {
			//设置默认值为true
		    private Boolean success=true;
		    private String msg;
		    //提供一个无参构造函数
		    public JsonResult(){}
		    //提供一个有参构造函数。当被new的时候就会被调用
		    public JsonResult(Boolean success, String msg) {
		        this.success = success;
		        this.msg = msg;
		    }
		    public Boolean getSuccess() {
		        return success;
		    }
		    public void setSuccess(Boolean success) {
		        this.success = success;
		    }
		    public String getMsg() {
		        return msg;
		    }
		    public void setMsg(String msg) {
		        this.msg = msg;
		    }
		}
	(2).在员工的controller类中写删除功能的后台代码
		//删除功能
		    @RequestMapping("/delete")
		    @ResponseBody//返回json数据
		    public JsonResult delete(Long id){
		        //处理下删除异常
		        try {
		            iEmployeeService.delete(id);
		        } catch (Exception e) {
		            e.printStackTrace();
		            //有异常。传个false,并且e.getMessage将异常信息传给前台
		            return new JsonResult(false,e.getMessage());
		        }
		        //没有异常。直接返回给前台
		        return new JsonResult();
		    }
	(3)删除功能的js代码
		//删除按钮事件
		        delete(){
		            //1.查看是否选中一行
		            var row=employeeDataGrid.datagrid("getSelected");
		            //2.如果没有选中行就给出提示
		            if(!row){
		                $.messager.alert('错误','请选择一行再操作','info')
		                return;
		            }
		                //3.选中的话,弹出提示框请用户确认是否删除
		                $.messager.confirm('提示','确认是否删除',function (r) {
		                    if(r){
		                //4.确认删除,后台进行删除.通过ajax请求。后台执行路径,{id:row.id}:获取到字段id,执行成功后的回调函数
		                        $.get("/employee/delete",{id:row.id},function (result) {
		                            //判断拿到回调函数的字段值是true还是false
		                            if(result.success){//执行的回调函数带过来的对象。通过对象.字段拿到值
		                                //true:成功删除后刷新页面
		                                employeeDataGrid.datagrid("reload");
		                            }else{
		                                //false:把失败信息做一个提示在消息框中。拿到对象中的字段msg值。后台代码是通过e.getMessage()封装的
		                                $.messager.alert('提示',`错误删除信息:${result.msg}`,'info');
		                            }
		                        })
		                    }
		                })
		        },
	(3)删除功能总结
		删除要根据前台传到后台的id值来进行删除。
		前台通过ajax请求,根据请求的url路径访问到后台删除程序,再根据传过来的id值进行删除,最后ajax的回调函数带着后台传过来的参数值做进一步的操作。

二.添加功能

(1)简要步骤
准备个弹出框,框中有个form表单,还有确认取消按钮,模态化(弹出框后不能再操作页面上的数据),form表单清空(弹出框填写数据后,下次再弹出框之前清空框中的数据)、验证功能
(2)弹出框jsp准备

<%--表单弹出框:点击添加修改按钮弹出的框。框中还有个form表单
        closed: true 默认框是关闭的、modal:true 模态框,弹出框后不能再操作页面上的数据、
        buttons:'#formBtns' 操作按钮和表单框关联 buttons 按钮在下方 toolbars:按钮在上方
    --%>
    <div id="employeeDialog" class="easyui-dialog" title="功能操作"
         data-options="iconCls:'icon-save',closed:true,modal:true,buttons:'#formBtns'"
         style="padding:10px">
        <form id="employeeForm" method="post">
            <input id="employeeId" type="hidden" name="id" />
            <table cellpadding="5">
                <tr>
                    <td>用户名:</td>
                    <td><input class="easyui-validatebox"  type="text" name="username" data-options="required:true,validType:'checkName'"></input></td>
                </tr>
                <tr data-show="false">
                    <td>密码:</td>
                    <td><input id="password" class="easyui-validatebox" type="text" name="password" data-options="required:true"></input></td>
                </tr>
                <tr data-show="false">
                    <td>确认密码:</td>
                    <td><input class="easyui-validatebox" type="text" name="repassword" validType="equals['password','id']" data-options="required:true"></input></td>
                </tr>
                <tr>
                    <td>邮箱:</td>
                    <td><input class="easyui-validatebox" type="text" name="email" data-options="required:true,validType:'email'"></input></td>
                </tr>
                <tr>
                    <td>年龄:</td>
                    <td><input class="easyui-validatebox" type="text" name="age" data-options="required:true,validType:'integerRange[18,60]'"></input></td>
                </tr>
                <tr>
                    <td>部门:</td>
                    <td>
                        <%--注意区别部门的两个下拉框。name="department.id":这个是部门下拉框是employee对象的部门的id;上面还有个部门的下拉框:name="departmentId":这个name是employeeQuery查询对象的部门的id--%>
                        <input name="department.id" class="easyui-combobox" panelHeight="auto"  style="width:120px"
                               data-options="required:true,valueField:'id',textField:'name',url:'/util/deptList'" />
                    </td>
                </tr>
            </table>
        </form>
    </div>
    <%--表单弹出框操作:确认和取消按钮--%>
    <div id="formBtns">
        <a href="javascript:;" data-method="save"  class="easyui-linkbutton c1">确认</a>
        <a href="javascript:;" onclick="$('#employeeDialog').dialog('close')" class="easyui-linkbutton c5">取消</a>
    </div>

(3)引用easyui的验证样式和验证功能的js文件
jeasyui.extensions.validatebox.css和jeasyui.extensions.validatebox.rules.js
jsp中凡是带有validType这样属性的,都是用了验证的功能。比如:
validType=“equals[‘password’,‘id’]”:引用easyui的验证功能js后的确认密码要跟id为password的密码一致功能。
validType:‘integerRange[18,60]’:引用easyui的验证功能js后的年龄验证功能,一个区间之内。
(4)自定义验证。用户名是否已被占用
Repository层

//用于做自定义的用户名验证。根据用户名查询到用户个数。Long类型的count就有值。 @Query("select count(o) from Employee o where username =?1") Long findCountByUsername(String username);
service层
IEmployeeService接口:

//根据用户名查询出用户。用于前台用户名的自定义验证
    boolean checkName(String username);

EmployeeServiceImpl实现类:

@Service
public class EmployeeServiceImpl extends BaseServiceImpl<Employee,Long>
        implements IEmployeeService {

    //先注入employeeRepository对象
    @Autowired
    private EmployeeRepository employeeRepository;
    //自定义用户名验证
    @Override
    public boolean checkName(String username) {
        //调用EmployeeRepositoryle接口中的findCountByUsername方法,根据用户名查询用户个数
        Long count = employeeRepository.findCountByUsername(username);
//        if(count>0){
//            //代表用户存在,返回false
//            return false;
//        }
//        //否则就不存在,返回true
//        return true;

        //优化上面代码
//        return count>0?false:true   三目运算
        //优化上面代码.count>0就是false,反过来就是true。
        return !(count>0);
    }
}

Controller层
EmployeeController类:

//自定义用户名验证
    @RequestMapping("/checkName")
    @ResponseBody
    public boolean checkName(Long id,String username){
        //添加功能时,判断用户名能否使用。
        return iEmployeeService.checkName(username);
    }

js部分:

//Easyui的自定义验证。用户名验证。注意:jquery同步请求:$.ajax ,同步请求返回的值是字符串
$.extend($.fn.validatebox.defaults.rules, {//验证框的固定格式
    //自定义验证的名称
    checkName: {
        /**
         * 参数含义:
         * @param value 输入用户名框中的值
         * @param param 调用验证输入的参数(数组)
         * @returns {boolean}
         */
        validator: function(value, param){
            //这里返回的是字符串。以前的get、post请求是jquery已转成json了的
            var result = $.ajax({
                url: "/employee/checkName",//请求后台路径
                data:{username:value},//传参
                async: false //同步请求。同步加载数据,如果异步请求会出问题
            }).responseText;
            //返回false代码验证失败,返回true代码验证成功
            return result==="true";//$.ajax返回的是字符串,这里就直接使用字符串
        },
        //出错后的信息
        message: '该用户名已经被使用'
    }
});

$(function () {
    //常用的控件先获取
    var employeeDataGrid =$("#employeeDataGrid");
    var searchForm =$("#searchForm");
    var employeeDialog=$("#employeeDialog");
    var employeeForm=$("#employeeForm")

    //注册方法.所有带有属性data-method的都注册注册事件
    $("*[data-method]").on("click",function(){
        //获取到属性中的具体方法
        var methodName = $(this).data("method");
        //调用方法。动态的调用方法
        itsource[methodName]();
    })

    itsource = {

        //添加按钮的事件
        add(){
            //点击按钮打开窗口,并且关闭后再次打开还是居于页面中间
            employeeDialog.dialog("open").dialog("center");
            //把form中的数据清空
            employeeForm.form("clear");
        },

jsp部分:
用户名栏就可以直接使用自定义的验证了
validType:‘checkName’

三.修改功能

(1)简要步骤
先判断是否选中一行数据来操作的、点击修改按钮弹出窗口,窗口中回显数据、修改时要传个id值到后台操作,自己原来的名字还是可以不需要更改就能使用、修改时不需要密码,添加操作时才显示密码框、处理部门的回显
(2)修改时用户名验证。自己原来的名字还是可以使用
在EmployeeController类中做一下判断即可

//自定义用户名验证
    @RequestMapping("/checkName")
    @ResponseBody
    public boolean checkName(Long id,String username){
        //修改功能。修改一行数据的时候。本身的名字还是可以使用。前台根据id传过来的名字和后台的一致,那么就可以使用
        if(id!=null){
            //1.根据id到数据库中获到数据
            Employee dbEmp = iEmployeeService.findOne(id);
            //2.判断数据库的员工名称和传过来的是否相等
            if(dbEmp.getUsername().equals(username)){
                //3.如果相等,代表这个用户名是可以使用的
                return true;
            }
        }
        //添加功能时,判断用户名能否使用。调用checkName方法
        return iEmployeeService.checkName(username);
    }

employee.jsp部分
设置个用于修改的隐藏域id

	<form id="employeeForm" method="post">
	            <%--在from表单中设置隐藏域id,用于修改的时候获取到id--%>
	            <input id="employeeId" type="hidden" name="id" />

在employee.js部分
拿到employee.jsp中的隐藏域id并传参到后台去查询

//Easyui的自定义验证。用户名验证。jquery同步请求:$.ajax ,同步请求返回的值是字符串
$.extend($.fn.validatebox.defaults.rules, {//验证框的固定格式
    //自定义验证的名称
    checkName: {
        /**
         * 参数含义:
         * @param value 输入用户名框中的值
         * @param param 调用验证输入的参数(数组)
         * @returns {boolean}
         */
        validator: function(value, param){
            //修改的时候,拿到相应的id。
            var empId = $("#employeeId").val();
            //这里返回的是字符串。以前的get、post请求是jquery已转成json了的
            var result = $.ajax({
                url: "/employee/checkName",//请求后台路径
                data:{username:value,id:empId},//传参,姓名和id值
                async: false //同步请求。同步加载数据,如果异步请求会出问题
            }).responseText;
            //返回false代码验证失败,返回true代码验证成功
            return result==="true";//$.ajax返回的是字符串,这里就直接使用字符串
        },
        //出错后的信息
        message: '该用户名已经被使用'
    }
});

$(function () {
    //常用的控件先获取
    var employeeDataGrid =$("#employeeDataGrid");
    var searchForm =$("#searchForm");
    var employeeDialog=$("#employeeDialog");
    var employeeForm=$("#employeeForm")
    //注册方法.所有带有属性data-method的都注册注册事件
    $("*[data-method]").on("click",function(){
        //获取到属性中的具体方法
        var methodName = $(this).data("method");
        //调用方法。动态的调用方法
        itsource[methodName]();
    })
     itsource = {
        //修改按钮的事件
        edit(){
            //1.查看是否选中一行
            var row=employeeDataGrid.datagrid("getSelected")
            //2.如果没有选中就给出提示
            if(!row){//有值就为true,没有值就为false
                $.messager.alert("提示","请先选中一行","info");
                return;
            }
            //点击按钮打开窗口,并且关闭后再次打开还是居于页面中间
            employeeDialog.dialog("open").dialog("center");
            //把form中的数据清空。先清空再回显
            employeeForm.form("clear");
            //部门回显
            //咱们部门要的字段:"department.id":有个叫department.id的字段
            // row的部门子段:  department.id:有个叫department的对象,对象中有id字段
            if(row.department){
                //将row的部门字段转换成部门要的字段
                row["department.id"] = row.department.id;
            }
            //修改时回显选中行的数据
            employeeForm.form("load",row);
        },

(3)添加和修改弹出框的保存按钮功能
employeeController类

//保存功能
    @RequestMapping("/save")
    @ResponseBody
    public JsonResult save(Employee employee){
        try {
            iEmployeeService.save(employee);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(false,e.getMessage());
        }
        return new JsonResult();
    }

js部分

		//保存功能
        save(){
            employeeForm.form('submit', {
                url:"/employee/save",
                //提交表单前的方法。做一些验证,如果为false,会阻止提交功能
                onSubmit: function(){
                    return $(this).form('validate');
                },
                //操作成功后的回调 {success:true,msg:xxx}
                success:function(data){//回调得到的data是JSON字符串
                    //将json字符串转换成json对象
                    //var result = eval("("+data+")");eval也可以
                    var result=JSON.parse(data);
                    //同样是后台common包中的JsonResult类中的字段success和msg
                    if(result.success){
                        //成功后刷新页面
                        employeeDataGrid.datagrid("reload");
                        //再关闭窗口
                        employeeDialog.dialog("close");
                    }else{
                        //把失败信息做一个提示
                        $.messager.alert("提示",`你出错了! 原因是:${result.msg}`,"error");
                    }
                }
            });
        },

(4)添加的时候显示密码框,修改的时候就不显示密码框
employee.jsp部分
给密码和确认密码去个名字(添加个data-show属性)

				<tr data-show="false">
                    <td>密码:</td>
                    <td><input id="password" class="easyui-validatebox" type="text" name="password" data-options="required:true"></input></td>
                </tr>
                <tr data-show="false">
                    <td>确认密码:</td>
                    <%--validType="equals['password','id']":引用easyui的验证功能js后的确认密码要跟id为password的密码一致功能--%>
                    <td><input class="easyui-validatebox" type="text" name="repassword" validType="equals['password','id']" data-options="required:true"></input></td>
                </tr>

在employee.js部分
修改的时候把所有带data-show的属性藏起来,添加的时候又显示出来

 //添加按钮的事件
        add(){
           
            //添加的时候把所有带data-show的元素显示出来
            $("*[data-show]").show();
           
            //点击按钮打开窗口,并且关闭后再次打开还是居于页面中间
            employeeDialog.dialog("open").dialog("center");
            //把form中的数据清空
            employeeForm.form("clear");
        },

        //修改按钮的事件
        edit(){
            //1.查看是否选中一行
            var row=employeeDataGrid.datagrid("getSelected")
            //2.如果没有选中就给出提示
            if(!row){//有值就为true,没有值就为false
                $.messager.alert("提示","请先选中一行","info");
                return;
            }
           
            //修改的时候把所有带data-show的元素隐藏起来
            $("*[data-show]").hide();
           
            //点击按钮打开窗口,并且关闭后再次打开还是居于页面中间
            employeeDialog.dialog("open").dialog("center");
            //把form中的数据清空。先清空再回显
            employeeForm.form("clear");
            //咱们部门要的字段:"department.id":有个叫department.id的字段
        // row的部门子段:  department.id:有个叫department的对象,对象中有id的字段
            if(row.department){
                //将row的部门字段转换成部门要的字段
                row["department.id"] = row.department.id;
            }
            //修改时回显选中行的数据
            employeeForm.form("load",row);
        },

(5)弹出框的保存按钮。(添加和修改的保存功能)
会遇到的问题:添加保存功能能正常执行,但是修改保存出现异常。
原因:密码验证环节出错。虽然点击修改按钮弹出的窗口已经将密码和确认密码这两个栏隐藏了去,但是还是隐藏的存在密码的验证功能。

后台controller部分
虽然添加和修改的保存操作是一样的,但是为了后期的权限考虑,需要将两者的操作分开来处理

//为了我后期的权限考虑,添加与修改的路径不能一样
    //保存功能
    @RequestMapping("/save")
    @ResponseBody
    public JsonResult save(Employee employee){
        //直接调用下面的方法
        return saveOrUpdate(employee);
    }

    //修改保存
    @RequestMapping("/update")
    @ResponseBody
    public JsonResult update(Employee employee){
        //直接调用下面的方法
        return saveOrUpdate(employee);
    }

    //添加或者修改方法
    private JsonResult saveOrUpdate(Employee employee){
        try {
            iEmployeeService.save(employee);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(false,e.getMessage());
        }
        return new JsonResult();
    }

在employee.js部分- -解决密码验证问题
怎么确定是添加的路径还是修改的路径。根据之前设置的隐藏域id有没有值来确定。然后修改保存还要禁用密码的验证功能

		//保存功能
        save(){
        
           	 //先默认是保存路径
            var url="/employee/save";
            //根据id来确定是添加的路径还是修改路径
                //根据form表单employeeForm的隐藏域id
            var id=$("#employeeId").val();
            //如果id有值就是修改路径
            if(id){
                url="/employee/update";
            }
            
            employeeForm.form('submit', {
                url:url,
                //提交表单前的方法。做一些验证,如果为false,会阻止提交功能
                onSubmit: function(){
                    return $(this).form('validate');
                },
                //操作成功后的回调 {success:true,msg:xxx}
                success:function(data){//回调得到的data是JSON字符串
                    //将json字符串转换成json对象
                    //var result = eval("("+data+")");eval也可以
                    var result=JSON.parse(data);
                    //同样是后台common包中的JsonResult类中的字段success和msg
                    if(result.success){
                        //成功后刷新页面
                        employeeDataGrid.datagrid("reload");
                        //再关闭窗口
                        employeeDialog.dialog("close");
                    }else{
                        //把失败信息做一个提示
                        $.messager.alert("提示",`你出错了! 原因是:${result.msg}`,"error");
                    }
                }
            });
        },

解决验证码问题
添加保存操作的时候开启

		//添加按钮的事件
        add(){
            //添加的时候把所有带data-show的元素显示出来
            $("*[data-show]").show();
            
            //添加的时候开启密码验证框。为了弹出框保存功能的正常执行
            $("*[data-show] input").validatebox("enable");
            
            //点击按钮打开窗口,并且关闭后再次打开还是居于页面中间
            employeeDialog.dialog("open").dialog("center");
            //把form中的数据清空
            employeeForm.form("clear");
        },

修改保存操作的时候禁用密码验证

		//修改按钮的事件
        edit(){
            //1.查看是否选中一行
            var row=employeeDataGrid.datagrid("getSelected")
            //2.如果没有选中就给出提示
            if(!row){//有值就为true,没有值就为false
                $.messager.alert("提示","请先选中一行","info");
                return;
            }
            //修改的时候把所有带data-show的元素隐藏起来
            $("*[data-show]").hide();
            
            //修改保存操作的时候禁用密码验证功能。为了弹出框保存功能的正常执行
            $("*[data-show] input").validatebox("disable");
            
            //点击按钮打开窗口,并且关闭后再次打开还是居于页面中间
            employeeDialog.dialog("open").dialog("center");
            //把form中的数据清空。先清空再回显
            employeeForm.form("clear");
            //咱们部门要的字段:"department.id":有个叫department.id的字段
        // row的部门子段:  department.id:有个叫department的对象,对象中有id的字段
            if(row.department){
                //将row的部门字段转换成部门要的字段
                row["department.id"] = row.department.id;
            }
            //修改时回显选中行的数据
            employeeForm.form("load",row);
        },

(6)以上的操作会造成数据的丢失
在修改保存的时候,密码和头像数据会丢失
原因:
在执行修改路径的时候,springmvc通过反射会给我们new一个对象出来,并将修改页面中的数据封装到对象中去传给后台保存。但是,修改按钮的弹出框并没有密码和头像栏,也就没有这两个字段的数据。执行保存,这两个字段就为null空值。造成这两个字段数据丢失。所以要告诉springmvc不要动那两个字段

解决办法:修改的时候不要动那两个字段就可以了
第一种:用隐藏域,在修改时将值也一并传过去。但是不安全且复杂
第二种:在不需要修改的字段上打注解@Column(updatable=false) 。但是以后修改会比较复杂

@Entity
@Table(name = "employee")
public class Employee extends BaseDomain{
    //密码
    @Column(updatable = false)//告诉springmvc,修改保存操作时不要动这个属性
    private String password;
    //头像
    @Column(updatable = false)//告诉springmvc,修改保存操作时不要动这个属性
    private String headImage;

第三种:springMVC框架已帮我们解决。以后其他的框架都有这个功能。原理:通过id拿到数据库中员工的值,然后将前台传过来的值进行设置覆盖。字段改变了的就设置后覆盖原来的数据,没有改变的就不管。
注解@ModelAttribute(“名字随便”)
作用:在执行任何一个路径(方法)之前,都会先来执行这个方法
controller代码部分

/**
     * 解决修改保存数据丢失问题:springMVC框架已提供了方法
     * 作用:在执行任何一个路径(方法) 之前都会先执行这个方法
     *跟下面的修改报保存功能相关联。
     *  此时查询出来的dbEmp对象就是下面修改保存中的employee对象。是一样的,
     *  只不过要进行改动字段值的设置覆盖,没有变动的字段不会去管
     */
    @ModelAttribute("editEmployee")
    public Employee beforeEdit(Long id){
        //修改的时候查询。id不为空(有值),就根据id查询出一个员工
        if(id!=null){
            Employee dbEmp = iEmployeeService.findOne(id);
            return dbEmp;
        }
        return null;
    }

还要跟修改保存路径相关联(“/updata”)
在参数类的前面@ModelAttribute(“editEmployee”)

	//@ModelAttribute("editEmployee"):解决数据丢失。和修改保存功能产生关联
    //修改保存
    @RequestMapping("/update")
    @ResponseBody
    public JsonResult update(@ModelAttribute("editEmployee")Employee employee){
        //直接调用下面的方法
        return saveOrUpdate(employee);
    }

(7)解决了数据丢失的问题,但是有出现了一个问题
问题:
所有需要参数id路径的方法执行的时候都要去执行@ModelAttribute(“editEmployee”)的方法,那会严重影响性能。
我只想修改的时候去查询
解决:
在employee.js代码
在保存功能的修改路径中传个参数过来

		//保存功能
        save(){
            //先默认是保存路径
            var url="/employee/save";
            //根据id来确定是添加的路径还是修改路径
                //根据form表单employeeForm的隐藏域id
            var id=$("#employeeId").val();
            
            //如果id有值就是修改路径
            if(id){
                //修改的时候传个参数cmd到后台,解决(数据丢失)只有修改才去查询员工数据,提高性能,否则任何路径执行时都要去查询。
                url="/employee/update?cmd=update";
            }
            
            employeeForm.form('submit', {
                url:url,
                //提交表单前的方法。做一些验证,如果为false,会阻止提交功能
                onSubmit: function(){
                    return $(this).form('validate');
                },
                //操作成功后的回调 {success:true,msg:xxx}
                success:function(data){//回调得到的data是JSON字符串
                    //将json字符串转换成json对象
                    //var result = eval("("+data+")");eval也可以
                    var result=JSON.parse(data);
                    //同样是后台common包中的JsonResult类中的字段success和msg
                    if(result.success){
                        //成功后刷新页面
                        employeeDataGrid.datagrid("reload");
                        //再关闭窗口
                        employeeDialog.dialog("close");
                    }else{
                        //把失败信息做一个提示
                        $.messager.alert("提示",`你出错了! 原因是:${result.msg}`,"error");
                    }
                }
            });
        },

employeeController类部分

//为了提高性能,在js保存功能部分的url为修改路径传一个名字为cmd的参数值update过来判断。
    @ModelAttribute("editEmployee")
    public Employee beforeEdit(Long id,String cmd){
        //只有修改才做查询。id不为空(有值)并且传过来的cmd值为update,才回去数据库查询员工出来
        if(id!=null && "update".equals(cmd)){
            Employee dbEmp = iEmployeeService.findOne(id);    
            return dbEmp;
        }
        return null;
    }

(8)以上功能实现后又会出现一个问题
问题:
只要你点击修改部门时,就会报n-To-n的错误
Department was altered from 1 To 2 的错误,
错误分析:
我们修改了一个持久化对象的id。
持久化对象从何处来的?
为什么部门这个持久化对象的id被修改,我操作的是员工部分?
原因:
在employee.jsp中的弹出框的部门栏中
标签中部门的name为department.id
springMVC只要发现传的字符串中有点(.)存在,那么它就会把这个字符串分开成department 和 id 。而符号点之前的都是调用get,只有最后一个使用set。
在employeeController类中,Employee dbEmp = iEmployeeService.findOne(id); dbEmp 一个持久化对象,
然后第一个是调用get方式:
Department dept=dbEmp .getDepartment()
第二个是set方式:
dept.setid=2,那么你就修改了就修改了dbEmp 这个持久化对象的id了,就会报错。
脏数据更新:只要持久化对象修改了,提交事务的时候就回去改对象,而id有不能改,所以就会报n-To-n的错

					<td>部门:</td>
                    <td>
                        <%--name="department.id":这个是employee对象的部门的id--%>
                        <input name="department.id" class="easyui-combobox" panelHeight="auto"  style="width:120px"
                               data-options="required:true,valueField:'id',textField:'name',url:'/util/deptList'" />
                    </td>

解决问题:
只需要在employeeController类部分修改
dbEmp.setDepartment(null);将传过来的对象设置为空
Department dept=dbEmp .getDepartment()这个dept就是空的,然后springMVC就会去帮你创建一个对象,dept=new Department()
那这个dept对象就不是持久化对象,只是员工中对应的部门的值。那么设置id时,dept。setId(2);就不会报错了
解决代码:

	@ModelAttribute("editEmployee")
    public Employee beforeEdit(Long id,String cmd){
        //只有修改才做查询。id不为空(有值)并且传过来的cmd值为update,才回去数据库查询员工出来
        if(id!=null && "update".equals(cmd)){
            Employee dbEmp = iEmployeeService.findOne(id);
            
            //解决n-to-n的问题(凡是要传过来的关联对象,都把它清空)
            dbEmp.setDepartment(null);
            
            return dbEmp;
        }
        return null;
    }

猜你喜欢

转载自blog.csdn.net/Abdullahi_kanye/article/details/88604744