【重点###】SpringDataJPA的组合条件分页查询(笔记思路,便于忘了复习)页面:EasyUI

1. 第一步:添加一个查询按钮,并且添加一个方法


 

function doSearch(){
				$('#searchWindow').window("open");
			}

2.第二步:完善查询按钮###

 

$(function(){
	 $("#searchBtn").click(function(){
		var formData = $("#searchForm").serializeJSON();
		$("#grid").datagrid("load",formData);//===不是作为请求参数?是的。封装请求和json返回
	})
					 
 })

3.第三步:在action中修改原来的findByPage方法

@Action("courierAction_findByPage")
	public void findByPage(){
//		QBC
//		DetachedCriteria dc = DetachedCriteria.forClass(Courier.class);
//		dc.add(Restrictions.like("", value));
		
//		model.getCourierNum()
//		工号	
//		model.getStandard().getName()
//		收派标准	
//		model.getCompany()
//		所属单位	
//		model.getType()
//		类型
		Specification<Courier> specification = new Specification<Courier>() {
			@Override
			public Predicate toPredicate(Root<Courier> root, CriteriaQuery<?> query, CriteriaBuilder cb) {  //===query在哪用?
//				Root<Courier> root,  当做查询的主体 courier
//				CriteriaQuery<?> query, 用来拼接查询条件 级别类似于Restrictions
//				CriteriaBuilder cb   ,用来拼接查询条件 级别类似于Restrictions
				
//				用来接收每次拼接的对象
				List<Predicate> list = new ArrayList<Predicate>();
//				工号	
				if(StringUtils.isNotBlank(model.getCourierNum())){
				  Predicate predicate1 = cb.like(root.get("courierNum").as(String.class), "%"+model.getCourierNum()+"%");
				  list.add(predicate1);
//				  return predicate;
				}
//				model.getCompany()
//				所属单位	
				if(StringUtils.isNotBlank(model.getCompany())){
					  Predicate predicate2 = cb.like(root.get("company").as(String.class), "%"+model.getCompany()+"%");
//					  return predicate;
					  list.add(predicate2);
				}
//				model.getType()
//				类型
				if(StringUtils.isNotBlank(model.getType())){
					  Predicate predicate3 = cb.like(root.get("type").as(String.class), "%"+model.getType()+"%");
//					  return predicate;
					  list.add(predicate3);
				}
				
//				model.getStandard().getName()
//				收派标准	===特殊。多及关联 
				if(  model.getStandard()!=null  &&  StringUtils.isNotBlank(model.getStandard().getName())  ){
//					  select c.* from courier c ,standard s where c.standardId = s.id   and s.name=?
					  Join<Object, Object> join = root.join("standard");  //看作standard的对象
					  Predicate predicate4 = cb.like(join.get("name").as(String.class), "%"+model.getStandard().getName()+"%");
//					  return predicate;
					  list.add(predicate4);
				}
				if(list.size()==0){
//					如果没有组装条件就直接return null
				  return null;
				}
//				list--->数组---->Predicate
				Predicate[] predicates = new Predicate[list.size()];
				predicates = list.toArray(predicates);
				
				return cb.and(predicates);
			}
		};

		//===上面都是为了创建 查询条件对象specification。===封装了hibernate的QBC离线查询。
		Pageable pageable  = new PageRequest(page-1, rows);
//		Page<Courier> page = service.findByPage(pageable);//===原来的findByPage(无条件查询全部+分页,简单)
		Page<Courier> page = service.findByPage(specification,pageable);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("total", page.getTotalElements());
		map.put("rows", page.getContent());
		//取消循环引用  不出现$ref
		String jsonString = JSON.toJSONString(map, SerializerFeature.DisableCircularReferenceDetect);
//		回写到浏览器上  
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setContentType("application/json;charset=utf-8");
		try {
			response.getWriter().write(jsonString);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
//		{total:100,rows:[{},{}]}
	}

service代码:

@Override
	public Page<Courier> findByPage(Specification<Courier> specification, Pageable pageable) {
		
		return dao.findAll(specification, pageable);
	}


dao代码:多继承一个父接口(dao本身就是个接口),可以继承它的 findAll(precision,pageable)方法。


====为什么是这个接口,下面dao代码里详解:(找到这个接口的过程)

import java.util.List;

import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;

import cn.itcast.bos.domain.base.PageBean;
import cn.itcast.bos.domain.base.Courier;

/**
 *Spring Data JPA :	优点:
 * dao没有实现类===极大地简化开发
 * 接口上不需要写注解
 *Spring Data JPA :	实现: 
 * ===dao extends JpaRepository<T, ID>
 * ===dao extends JpaRepository<Courier, Integer>
 * @author syl
 *
 *
 *
 *====###### 【Spring Data JPA :	组合条件查询  】
 *=====【查找JpaRepository的父类,父接口 中带有 Specification参数的方法。。。===没找到。
 *在父接口的其他实现类里找到。。。找到: findAll(Specification<T> spec, Pageable pageable)】
 *
 *====###### 【只要能找到 有符合条件的方法的类或接口就行。】######  不必一定是父类和父接口。。。。
 *====###### 【只要能实现功能就行。】
 *最好找到:JpaSpecificationExecutor<T>接口
 *
 *
 *====SimpleJpaRepository是类(CRUDProperty类的默认代理类(实现类)),不能和接口JpaRepository一起被 接口继承。。。
 *===JpaSpecificationExecutor<T>是接口,能和接口JpaRepository一起被 接口继承。。。
 *
 */
public interface CourierDao extends JpaRepository<Courier, Integer>, JpaSpecificationExecutor<Courier> {

	 //<S> S save( Courier Courier);
	//==######= save、这样的操作是可提取的  重复代码,保存任何类型对象,都可以通过反射拿到类型对象,再保存。
	//===所以这里JpaRepository提供了save方法。
	//===Spring Data Jpa 是个规范接口框架。真正操作数据库的还是hibernate。只是对操作进一步封装,简化。
	//===所以这里不用自定义 save方法!!!
	
	//===自定义查询方法:方法名命名有规则。
	List<Courier> findByName(String string);

	//==######=1、【自定义查询方法】【解析查询方法名】===Spring Data Jpa不可能知道每个实体的每个属性。
//	@Query("from Courier where name=?")  //方式一:jpql=====【写法和HQL一样的】
	@Query(value="select * from T_Courier where C_NAME=?",nativeQuery=true)  //方式二:sql
	List<Courier> findByXXXX(String string);

	//==######=2、【自定义更新方法】【更新方法名不会被解析】。所以要加一个@Modifying告诉程序要干什么 
	//@Query(value="update Courier set name=? where id=?")//方式一:jpql=====【写法和HQL一样的】
	@Query(value="update T_Courier set C_NAME=? where C_ID=?",nativeQuery=true)//方式二:sql  
	@Modifying   //==######=如果涉及到数据修改需要加 modifying注解
	void updateName(String string, int i);
	
	
	@Query(value="update Courier set deltag='1' where id=?")//方式一:jpql=====【写法和HQL一样的】
	//@Query(value="update T_Courier set C_DELTAG='1' where C_ID=?",nativeQuery=true)//方式二:sql  
	@Modifying 
	void updateDeltag(int parseInt);

	//List<Courier> findAll(PageBean pageBean);

	
}

============注意这里加深理解struts2 模型驱动的使用:

泛型指定实体类相关属性的所有表单,请求过来都能封装。===例如 查询条件 表单。。。


========页面:EasyUI。

======【注意使用的是html】html静态页面相对于jsp等动态页面有很大好处。依赖少,加载资源少。

===【互联网项目都不敢用jsp的,容易卡死。(页面依赖太多jar包:servlet、jsp.jar、JSTL相关的 standard.jar...)。 例如京东的页面就用的html】



第一步 第二步看不懂就看这里:完整页面:

<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<title>管理取派员</title>
		<!-- 导入jquery核心类库 -->
		<script type="text/javascript" src="../../js/jquery-1.8.3.js"></script>
		<!-- 导入easyui类库 -->
		<link rel="stylesheet" type="text/css" href="../../js/easyui/themes/default/easyui.css">
		<link rel="stylesheet" type="text/css" href="../../js/easyui/themes/icon.css">
		<link rel="stylesheet" type="text/css" href="../../js/easyui/ext/portal.css">
		<link rel="stylesheet" type="text/css" href="../../css/default.css">
		<script type="text/javascript" src="../../js/easyui/jquery.easyui.min.js"></script>
		<script type="text/javascript" src="../../js/easyui/ext/jquery.portal.js"></script>
		<script type="text/javascript" src="../../js/easyui/ext/jquery.cookie.js"></script>
		<script src="../../js/easyui/locale/easyui-lang-zh_CN.js" type="text/javascript"></script>
		<!-- 一步提交form序列化 -->
		<script src="../../js/jquery.serializejson.min.js" type="text/javascript"></script>
		
		<script type="text/javascript">
		
			$(function(){
				
				//保存。点击提交表单
				$("#saveBtn").click(function(){
					if($("#addForm").form("validate")){
						//$("#addForm").submit();
						$.post(
							"../../CourierAction_save.action",
							$("#addForm").serializeJSON(),
							function(data){
	//	 						data={"success":true|false,"message":"保存成功"|"保存失败"}
								if(data.success){
	//	 							1、关闭窗口
		                              $("#addWindow").window('close');
	//	 							2、刷新表格===######
		                              $("#grid").datagrid("reload"); //刷新后保留在当前页######
	//	                               $("#grid").datagrid("load"); //刷新后跳转到第一页
								}
	//	 							3、alert提示
								   $.messager.alert("提示",data.message);
										
							},"json");
						//===一次请求完毕,清空form。===第二次添加默认回显上次添加的内容
						$("#addForm").form("clear");
					}
					
				});
				
				//=========【EasyUI分页查询不难,pageable属性就搞定。====================================================
				//=========【重难点(超容易忘)】:【难在EasyUI【加条件的分页查询】之【提交查询表单数据的方式(很特别!):
				//=========不发Ajax请求,而是使用grid的load方法(自带发送请求和返回数据)】
				//=========页面写法【固定的(目前没有其他方案)】=不用API load这个方案总是报错:当前页号不能小于0。=查询的js代码。====================================================
				 $("#searchBtn").click(function(){
					var formData = $("#searchForm").serializeJSON();
					 $("#grid").datagrid("load",formData);//刷新后跳转到第一页
					 //$("#grid").datagrid("reload",formData);//刷新后保留在当前页(结果的页号)######
					 //######【只能用load不要用reload】 reload保留在当前页, 结果的最大页号可能都小于初始页码号。这时页面有bug。【所以只能用load不要用reload】
					 
					 //===作为请求参数?是 
					 //###### 【datagrid的load方法,带参数,会发一次带参请求。load返回值就是服务器返回的json数据。】并自动刷新页面。。。
					 //===datagrid("load",formData)极大地简化了 发送请求。【不用再写一大串 Ajax请求了。。。】O(∩_∩)O哈哈~
					 
					 //===请求完毕  刷新【老师没写】
				 }) 
				
			/* 	//=====我的方式:
				//=====datagrid("load",formData)极大地简化了grid发送请求。【不用再写一大串 Ajax请求了。。。】
				//====【自己写了访问Ajax请求。反而总报错】页号不能小于0,找了两个多小时,还是没找到错误。如下: 
			//查询。点击提交表单
				$("#searchBtn").click(function(){
					if($("#searchForm").form("validate")){
						//$("#addForm").submit();
						$.post(
							"../../CourierAction_searchByPage.action",
							$("#searchForm").serializeJSON(),
							function(data){
	//	 						data={"success":true|false,"message":"保存成功"|"保存失败"}
								if(data.success){
	//	 							1、关闭窗口
		                              $("#searchWindow").window('close');
	//	 							2、刷新表格===######
		                              $("#grid").datagrid("reload"); //刷新后保留在当前页######
	//	                               $("#grid").datagrid("load"); //刷新后跳转到第一页
								}
	//	 							3、alert提示
								   $.messager.alert("提示",data.message);
										
							},"json");
						//===一次请求完毕,清空form。===第二次添加默认回显上次添加的内容
						$("#searchForm").form("clear");
					}
					
				});*/
				
				
				
			});	
		
			function doAdd(){
				$('#addWindow').window("open");//弹窗口
			}
			
			function doEdit(){
				//alert("修改...");
				var arr = $("#grid").datagrid("getSelections")
				if (arr.length!=1) {
					alert("请选择一条要修改的数据");
					return;
				}
				$("#addForm").form("load",arr[0]);
				//===保存还是调用  添加 save()
			}
			
			function doDelete(){
				//alert("删除...");
				var arr = $("#grid").datagrid("getSelections")
				if (arr.length==0) {
					alert("请选择要作废的数据");
					return;
				}
				
				var ids = new Array();
				//for (var i = 0; i < array.length; i++) {
				for (var i = 0; i < arr.length; i++) {
					//ids.push(arr[i]);
					ids.push(arr[i].id);
				}
				var idsStr = ids.join(",");
				//alert(idsStr);
				
				$.post(
						"../../CourierAction_deleteBatch.action",
					{"ids":idsStr},
					function(data){
//	 						data={"success":true|false,"message":"保存成功"|"保存失败"}
							if(data.success){
//	 							2、刷新表格===######
	                              $("#grid").datagrid("reload"); //刷新后保留在当前页######
//	                               $("#grid").datagrid("load"); //刷新后跳转到第一页
							}
//	 							3、alert提示
							   $.messager.alert("提示",data.message);
									
						},"json");
			}
			
			function doRestore(){
				alert("将取派员还原...");
			}
			
			function doSearch(){
				//查询
				$("#searchWindow").window("open");
			}
			
			//工具栏
			var toolbar = [ {
				id : 'button-add',	
				text : '增加',
				iconCls : 'icon-add',
				handler : doAdd
			}, {
				id : 'button-edit',
				text : '修改',
				iconCls : 'icon-edit',
				handler : doEdit
			}, {
				id : 'button-delete',
				text : '作废',
				iconCls : 'icon-cancel',
				handler : doDelete
			},{
				id : 'button-restore',
				text : '还原',
				iconCls : 'icon-save',
				handler : doRestore
			},{
				id : 'button-search',
				text : '查询',
				iconCls : 'icon-search',
				handler : doSearch
			}];
			// 定义列
			var columns = [ [ {
				field : 'id',
				checkbox : true,
			},{
				field : 'courierNum',
				title : '工号',
				width : 80,
				align : 'center'
			},{
				field : 'name',
				title : '姓名',
				width : 80,
				align : 'center'
			}, {
				field : 'telephone',
				title : '手机号',
				width : 120,
				align : 'center'
			}, {
				field : 'checkPwd',
				title : '查台密码',
				width : 120,
				align : 'center'
			}, {
				field : 'pda',
				title : 'PDA号',
				width : 120,
				align : 'center'
			}, {
				field : 'standard.name',
				title : '取派标准',
				width : 120,
				align : 'center',
				formatter : function(data,row, index){
					if(row.standard != null){
						//alert(row.standard.name);
						//====###### 【页面显示 '取派标准'相同的'取派标准'显示失败。。。 】
						return row.standard.name;
					}
					return "";
				}
			}, {
				field : 'type',
				title : '取派员类型',
				width : 120,
				align : 'center'
			}, {
				field : 'company',
				title : '所属单位',
				width : 200,
				align : 'center'
			}, {
				field : 'deltag',
				title : '是否作废',
				width : 80,
				align : 'center',
				formatter : function(data,row, index){
					if(data=="1"){
						return "已作废";
					}else{
						return "正常使用";
					}
				}
			}, {
				field : 'vehicleType',
				title : '车型',
				width : 100,
				align : 'center'
			}, {
				field : 'vehicleNum',
				title : '车牌号',
				width : 120,
				align : 'center'
			} ] ];
			
			$(function(){
				// 先将body隐藏,再显示,不会出现页面刷新效果
				$("body").css({visibility:"visible"});
				
				// 取派员信息表格
				$('#grid').datagrid( {
					iconCls : 'icon-forward',
					fit : true,
					border : false,
					rownumbers : true,
					striped : true,
					pageList: [3,5,9],
					pagination : true,
					toolbar : toolbar,
					//url : "../../data/courier.json",
					url : "../../CourierAction_findByPage",//==ok==【分页查询ok】
					//url : "../../CourierAction_searchByPage",//self==ok==【分页查询ok】
					//==######=页面初始化和 条件查询 共用一个 分页查询。
					//====【所有grid使用 Ajax请求地方都换成grid的 load方法。 form的load不能发请求?】
					idField : 'id',
					columns : columns,
					onDblClickRow : doDblClickRow
				});
				
				// 添加取派员窗口
				$('#addWindow').window({
			        title: '添加取派员',
			        width: 800,
			        modal: true,//===模态窗口
			        shadow: true,
			        closed: true,
			        height: 400,
			        resizable:false
			    });
				
			});
		
			function doDblClickRow(){
				alert("双击表格数据...");
			}
		</script>
	</head>

	<body class="easyui-layout" style="visibility:hidden;">
		<div region="center" border="false">
			<table id="grid"></table>
		</div>
		<div class="easyui-window" id="addWindow" title="对收派员进行添加或者修改"  collapsible="false" minimizable="false" maximizable="false" style="top:20px;left:200px">
			<div region="north" style="height:31px;overflow:hidden;" split="false" border="false">
				<div class="datagrid-toolbar">
					<a id="saveBtn" icon="icon-save" href="#" class="easyui-linkbutton" plain="true">保存</a>
				</div>
			</div>

			<div region="center" style="overflow:auto;padding:5px;" border="false">
				<form id="addForm">
					<table class="table-edit" width="80%" align="center">
						<tr class="title">
							<td colspan="4">收派员信息</td>
						</tr>
						<tr>
							<td>快递员工号</td>
							<td>
								<input type="text" name="courierNum" class="easyui-validatebox" required="true" />
							</td>
							<td>姓名</td>
							<td>
								<input type="text" name="name" class="easyui-validatebox" required="true" />
							</td>
						</tr>
						<tr>
							<td>手机</td>
							<td>
								<input type="text" name="telephone" class="easyui-validatebox" required="true" />
							</td>
							<td>所属单位</td>
							<td>
								<input type="text" name="company" class="easyui-validatebox" required="true" />
							</td>
						</tr>
						<tr>
							<td>查台密码</td>
							<td>
								<input type="text" name="checkPwd" class="easyui-validatebox" required="true" />
							</td>
							<td>PDA号码</td>
							<td>
								<input type="text" name="pda" class="easyui-validatebox" required="true" />
							</td>
						</tr>
						<tr>
							<td>快递员类型</td>
							<td>
								<input type="text" name="type" class="easyui-validatebox" required="true" />
							</td>
							<td>取派标准</td>
							<td>
								<!-- ===class="easyui-combobox"  -->
								<input type="text" name="standard.id" 
										class="easyui-combobox" 
										data-options="required:true,valueField:'id',textField:'name',
											url:'../../standard_findAll.action'"/>
							</td>
						</tr>
						<tr>
							<td>车型</td>
							<td>
								<input type="text" name="vehicleType" class="easyui-validatebox" required="true" />
							</td>
							<td>车牌号</td>
							<td>
								<input type="text" name="vehicleNum" class="easyui-validatebox" required="true" />
							</td>
						</tr>
					</table>
				</form>
			</div>
		</div>
		
		<!-- 查询快递员-->
		<div class="easyui-window" title="查询快递员窗口" closed="true" id="searchWindow" collapsible="false" minimizable="false" maximizable="false" style="width: 400px; top:40px;left:200px">
			<div style="overflow:auto;padding:5px;" border="false">
				<form id="searchForm">
					<table class="table-edit" width="80%" align="center">
						<tr class="title">
							<td colspan="2">查询条件</td>
						</tr>
						<tr>
							<td>工号</td>
							<td>
								<input type="text" name="courierNum" />
							</td>
						</tr>
						<tr>
							<td>收派标准</td>
							<td>
								<input type="text" name="standard.name" />
							</td>
						</tr>
						<tr>
							<td>所属单位</td>
							<td>
								<input type="text" name="company" />
							</td>
						</tr>
						<tr>
							<td>类型</td>
							<td>
								<input type="text" name="type" />
							</td>
						</tr>
						<tr>
							<td colspan="2"><a id="searchBtn"  class="easyui-linkbutton" data-options="iconCls:'icon-search'">查询</a> </td>
						</tr>
					</table>
				</form>
			</div>
		</div>
	</body>

</html>






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值