一.完成了高级分页查询
1.1 分页查询
1.1.1 准备分页条 pagination:true
<table class="easyui-datagrid" id="employeeDataGrid"
data-options="... pagination:true">
...
1.1.2 后台返回分页数据
需要返回的结构:{total:23,rows:[...]}
准备相应的UIPage类
public class UIPage<T> {
private Long total; //总条数
private List<T> rows; //每页数据
public UIPage(Page page) {
total = page.getTotalElements();
rows = page.getContent();
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
}
EmployeeController中添加返回UIPage的方法
/**
* 准备分页方法
* @param query
* @return
*/
@RequestMapping("/page")
@ResponseBody
public UIPage page(EmployeeQuery query){
//return employeeService.queryPage(query);
return new UIPage(employeeService.queryPage(query));
}
1.1.3 后台接收分页数据
我们必需保证前台传的数据(当前页与每页条数)和咱们后台的Query中的名称相同 BaseQuery中做修改
//兼容easyui的分页 ctrl+f9
public void setPage(int currentPage) {
this.currentPage = currentPage;
}
public void setRows(int pageSize) {
this.pageSize = pageSize;
}
1.2 完善咱们的Employee功能
1.2.1 完成Department的CRUD
拷备Employee再写一份即可
代码略(靠自己)
1.2.2 Employee对象
@Entity
@Table(name = "employee")
public class Employee extends BaseDomain {
...
//头像
private String headImage;
//部门
/**
* hibernate自动为懒加载对象加上了一些属性
* 但是这几个属性在SpringMVC生成json数据的数据,就会报错(No serializer)
* Ignore:忽视
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
//@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
private Department department;
...
}
1.2.3 懒加载引发的血案
1.2.3.1 noSession
EntityManager提前关系了
- web.xml中配置Spring的过滤器
<!--解决no-session的问题-->
<filter>
<filter-name>openEntityManager</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManager</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.2.3.2 noSerializer
hibernate添加了一些字段(变成Json时报错)
解决方案一: 字段上加注解 @JsonIgnoreProperties(value={“hibernateLazyInitializer”,“handler”,“fieldHandler”})
解决方案二:自己配置(拷备过来用即可)
CustomMapper
public class CustomMapper extends ObjectMapper {
public CustomMapper() {
this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 设置 SerializationFeature.FAIL_ON_EMPTY_BEANS 为 false
this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
}
}
applicationContext-mvc.xml
<!-- Spring MVC 配置 -->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json; charset=UTF-8</value>
<value>application/x-www-form-urlencoded; charset=UTF-8</value>
</list>
</property>
<!-- No serializer:配置 objectMapper 为我们自定义扩展后的 CustomMapper,解决了返回对象有关系对象的报错问题 -->
<property name="objectMapper">
<bean class="cn.itsource.aisell.common.CustomMapper"></bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
1.2.4 头像与部门的显示
employee.js加上format的方法
/**
*
* @param v(value) :当前的数据
* @param r(row) : 当前行的数据
* @param i(index) :索引
* @returns {string}
*/
function imageFormat(v,r,i) {
return `<img src='${v}' style="width:60px;height:60px;">`;
}
//部门的格式化
function deptFormat(v) {
return v?v.name:"";
}
employee中的index.js 使用format方法
<table class="easyui-datagrid" id="employeeDataGrid"
data-options="url:'/employee/page',fitColumns:true,singleSelect:true,fit:true,toolbar:'#toolbar',pagination:true">
<thead>
...
<th data-options="field:'headImage',width:100,formatter:imageFormat">头像</th>
...
<th data-options="field:'department',width:100,formatter:deptFormat">部门</th>
</tr>
</thead>
</table>
1.3 高级查询
1.3.1 准备高级查询的条件
<div id="toolbar">
...
<form id="searchForm" method="post">
用户名: <input name="username" class="easyui-textbox" style="width:80px">
邮箱: <input name="email" class="easyui-textbox" style="width:80px">
部门: <input class="easyui-combobox" name="departmentId"
data-options="valueField:'id',textField:'name',url:'/department/findAll',panelHeight:'auto'" />
<a href="#" data-method="search" class="easyui-linkbutton" iconCls="icon-search">查询</a>
</form>
</div>
1.3.2 准备search方法
注:我们引入了**jquery的扩展js(jquery.jdirk.js)**才有serializeObject方法
itsource = {
...
//高级查询
search(){
//JQuery没有提供拿到json格式的数据
//直接拿到要查询的值 {username:xx,...}
var params =searchForm.serializeObject();
// //grid刷新
employeeDataGrid.datagrid('load',params);
}
};
二.删除功能
2.1 准备一个JsonResult类型
/**
- 删除返回的信息
*/
public class JsonResult {
//代表是否成功
private boolean success = true;
//代表相应的信息(一般是错误信息)
private String msg;
public JsonResult(){}
public JsonResult(boolean success, String msg) {
this.success = success;
this.msg = msg;
}
...
}
2.2 EmployeeController提供删除功能
/**
- 前台会传一个id过来
- 需要返回:{success:true/false,msg:“xx”}
-
返回这种结构有两种方法:1种是**写map**, 1种是**直接返回对象**
*/
@RequestMapping("/delete")
@ResponseBody
public JsonResult delete(Long id){
try {
employeeService.delete(id);
return new JsonResult();
} catch (Exception e) {
e.printStackTrace();
//失败后返回的结果
return new JsonResult(false,e.getMessage());
}
}
2.3 employee.js完成删除
delete () {
//1.拿到你选择的那一条数据 (easyui的datagrid中有这个功能)
// row就是你选择的这一行的数据
var row = employeeDataGrid.datagrid("getSelected");
//2.如果没有拿到数据,给一个提示,让他选中再执行(后面的代码就不运行) Messager alert
if(row==null){
//alert("没有货,滚蛋!"); //不建议使用 1.不同浏览器效果不一样 2.它会阻塞进程
$.messager.alert('警告','没有货,滚蛋!',"info");
return;
}
//3.如果拿到数据,给一个提示,是否要删除? Messager confirm
$.messager.confirm('确认','您要狠心的干掉我嘛?',function(r){
if (r){
//4.如果要删除 -> 发送Ajax请求到后台进行数据删除 $.get/post("/employee/delete",{id:2},function(){....})
// 后台会返回相应的数据 :{success:true/false,msg:xxx}
// 如果成功,刷新datagrid
$.get("/employee/delete",{id:row.id},function (result) {
if(result.success){
//删除成功,刷新datagrid
employeeDataGrid.datagrid("reload");
}else{
//删除失败,给出失败提示
$.messager.alert('失败','删除没有成功,原因是:'+result.msg,"error");
}
})
}
});
},
三.添加功能
3.1 准备添加的弹窗
<%--添加或者修改的弹出框--%>
<div id="editDialog" class="easyui-dialog" title="数据操作" style="padding: 25px; "
data-options="iconCls:'icon-save',resizable:true,modal:true,buttons:'#btns',closed:true">
<form id="editForm" method="post">
<table>
<tr>
<td>名称</td>
<td><input class="easyui-validatebox" type="text" name="username" data-options="required:true" /></td>
</tr>
<tr>
<td>密码</td>
<td><input class="easyui-validatebox" type="text" name="password" data-options="required:true" /></td>
</tr>
<tr>
<td> 邮箱</td>
<td><input class="easyui-validatebox" type="text" name="email" data-options="required:true" /></td>
</tr>
<tr>
<td> 年龄</td>
<td><input class="easyui-validatebox" type="text" name="age" data-options="required:true" /></td>
</tr>
<tr>
<td> 部门</td>
<td>
<input class="easyui-combobox" name="department.id"
data-options="valueField:'id',textField:'name',url:'/department/findAll',panelHeight:'auto',required:true" />
</td>
</tr>
</table>
</form>
<div id="btns">
<a href="javascript:;" data-method="save" class="easyui-linkbutton c2" data-options="iconCls:'icon-ok'">确定</a>
<a href="javascript:;" data-method="close" class="easyui-linkbutton c5" data-options="iconCls:'icon-cancel'">取消</a>
</div>
</div>
3.2 点击添加弹出容器
//添加(只是弹出form)
add(){
//打开面板前把里面的数据清除
editForm.form("clear");
//把添加框(editDialog)打开
editDialog.dialog("center").dialog("open");
}
3.3 后台准备添加功能
/**
* 前台会传相应的数据(Employee)过来
* 需要返回:JsonResult{success:true/false,msg:"xx"}
*/
@RequestMapping("/save")
@ResponseBody
public JsonResult save(Employee employee){
try {
employeeService.save(employee);
return new JsonResult();
} catch (Exception e) {
e.printStackTrace();
return new JsonResult(false,e.getMessage());
}
}
3.4 前台提交form表单
save(){
/**
* 1.把表单数据传到后台
* 2.如果后台保存成功,返回{success:true},刷新页面
* 失败:返回{success:false,msg:xxx}
* 3.关闭弹出框
*/
/**
* 1.把表单数据传到后台
*/
editForm.form('submit', {
url:"/employee/save", //提交的路径
//提交前做点什么 如果返回false,它就不提交数据
onSubmit: function(){
// do some check
// return false to prevent submit;
return $(this).form('validate');
},
//data是一个json字符串
success:function(data){
// {"success":true}
//把一个Json字符串转成JSON对象
//eval("("+data+")")
var result = JSON.parse(data);
if(result.success){
//成功就刷新页面
employeeDataGrid.datagrid("reload");
}else{
$.messager.alert('警告',`添加失败,原因是:${result.msg}`,"info");
}
//关闭面板
itsource.close();
}
});
},
修改功能
1.1 在form中加上id
1.2 点击修改回显
itsource ={
...
update () {
//1.拿到选中的那一条数据
var row = employeeDataGrid.datagrid("getSelected");
//2.如果没有选中,给出提示
if(row==null){
$.messager.alert('警告','没有货,滚蛋!',"info");
return;
}
//3.清空表单并弹出数据
editForm.form("clear");
editDialog.dialog("center").dialog("open");
//4.完成咱们的数据回显
/**
* 部门的回显
*/
if(row.department){
row["department.id"] = row.department.id;
}
editForm.form("load",row);
}
}
1.3 save(保存)和update(修改)分开
1.3.1 前端请求改变
//保存修改功能(调用后台保存)
save(){
//添加功能的路径
var url ="/employee/save";
//拿到表单中的员工id,如果id存在,代表修改
var employeeId = $("#employeeId").val();
if(employeeId){
url = "/employee/update?cmd=update";
}
/**
* 1.把表单数据传到后台
*/
editForm.form('submit', {
url:url, //提交的路径
...
});
},
1.3.2 后台方法添加
/**
* 前台会传相应的数据(Employee)过来
* 需要返回:JsonResult{success:true/false,msg:"xx"}
*/
@RequestMapping("/save")
@ResponseBody
public JsonResult save(Employee employee){
return this.saveOrUpdate(employee);
}
//修改方法
@RequestMapping("/update")
@ResponseBody
public JsonResult update(Employee employee){
return this.saveOrUpdate(employee);
}
//添加或者修改
public JsonResult saveOrUpdate(Employee employee){
try {
employeeService.save(employee);
return new JsonResult();
} catch (Exception e) {
e.printStackTrace();
return new JsonResult(false,e.getMessage());
}
}
**
.数据丢失
**
2.1 数据丢失的原因
前台没有传过来
后台对象对没有传过来的值就设置为空
修改的时候执行sql就把空值设置进去、
2.2 数据丢失的解决方案
前台传过来(隐藏域)
sql不修改相应的字段
自己写sql直接控制
jpa在字段上加 @Column(updatable = false)
通过id获取对象,再把传过来的参传过来、
这些解决方案:动态更新
2.3 解决数据丢失的代码
咱们解决了数据丢失后修改员工的部门时会出现一个n-to-n的错误,在获取员工对象后把它的部门设置为Null即可解决
2.3.1 更新前的操作
/**
* @ModelAttribute:只要你通过前台调用我的方法,我就要执行这个方法中的内容
*
*/
@ModelAttribute("editEmployee")
public Employee beforeUpdate(Long id,String cmd){
//我想要的是,只有修改执行相应功能
if(id!=null && "update".equals(cmd)) {
//根据id拿到相应的对象
Employee employee = employeeService.findOne(id);
//把关连对应的值设置为空,就可以解决n-to-n的问题
employee.setDepartment(null);
return employee;
}
return null;
}
2.3.2 修改方法获取Employee对象
//修改方法
/**
*我们的这个employee对象中从 beforeUpdate中获取的
*/
@RequestMapping("/update")
@ResponseBody
public JsonResult update(@ModelAttribute("editEmployee") Employee employee){
return this.saveOrUpdate(employee);
}