我可以用jqGrid实现延迟加载吗?

我有一个超过5000个数据记录的网格。 这些数据每天都在增长。 当我用网格加载页面时,在网格显示数据之前需要差不多一分钟,我必须一次显示10行。

是否有可能使用此jqGrid实现延迟加载?

这是我生成JSon String的动作:

@RequestMapping(value = "studentjsondata", method = RequestMethod.GET) public @ResponseBody String studentjsondata(HttpServletRequest httpServletRequest) { Format formatter = new SimpleDateFormat("MMMM dd, yyyy"); String column = "id"; if(httpServletRequest.getParameter("sidx") != null){ column = httpServletRequest.getParameter("sidx"); } String orderType = "DESC"; if(httpServletRequest.getParameter("sord") != null){ orderType = httpServletRequest.getParameter("sord").toUpperCase(); } int page = 1; if(Integer.parseInt(httpServletRequest.getParameter("page")) >= 1){ page = Integer.parseInt(httpServletRequest.getParameter("page")); } int limitAmount = 10; int limitStart = limitAmount*page - limitAmount; List students = Student.findAllStudentsOrderByColumn(column,orderType,limitStart,limitAmount).getResultList(); List countStudents = Student.findAllStudents(); double tally = Math.ceil(countStudents.size()/10.0d); int totalPages = (int)tally; int records = countStudents.size(); StringBuilder sb = new StringBuilder(); sb.append("{\"page\":\"").append(page).append("\", \"records\":\"").append(records).append("\", \"total\":\"").append(totalPages).append("\", \"rows\":["); boolean first = true; for (Student s: students) { sb.append(first ? "" : ","); if (first) { first = false; } sb.append(String.format("{\"id\":\"%s\", \"cell\":[\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"]}",s.getId(), s.getId(), s.getFirstName(), s.getLastName(), formatter.format(s.getDateOfBirth().getTime()), s.getGender(), s.getMaritalStatus())); } sb.append("]}"); return sb.toString(); } 

这是jqGrid的页面:

 $("#studentGrid").jqGrid({ url: '/starburst/programmes/studentjsondata', datatype: 'json', height: 'auto', colNames:['id','First Name', 'Last Name', 'Date Of Birth', 'Gender', 'Marital Status'], colModel:[ {name:'id',index:'id', width:15}, {name:'firstName',index:'firstName', width:30, formoptions:{elmprefix:'(*) '}, editable:true, edittype: 'text', editrules:{required:true}}, {name:'lastName',index:'lastName', width:30, formoptions:{elmprefix:'(*) '}, editable:true, edittype: 'text',editrules:{required:true}}, {name:'dateOfBirth',index:'dateOfBirth', width:30, formoptions:{elmprefix:'(*) '},editrules:{required:true}, editable:true, edittype: 'text', editoptions: { dataInit: function(element) { $(element).datepicker({dateFormat: 'MM dd, yy'}) } } }, {name:'gender',index:'gender', width:30, formoptions:{elmprefix:'(*) '}, editable:true, editrules:{required:true}, edittype: 'select', editoptions:{value:{}} }, {name:'maritalStatus',index:'maritalStatus', width:30, formoptions:{elmprefix:'(*) '}, editable:true, editrules:{required:true}, edittype: 'select', editoptions:{value:{}} } ], rowNum:10, autowidth: true, pager: '#pager', sortname: 'id', viewrecords: true, sortorder: "desc", caption:"Students", emptyrecords: "Empty Records", subGrid: true, /*  */ }); $("#studentGrid").jqGrid('navGrid', "#pager", {edit:false,add:false,del:false,search:true},{ },{ },{ }, { sopt:['eq', 'ne', 'lt', 'gt', 'cn', 'bw', 'ew'], closeOnEscape: true, multipleSearch: true, 

请参阅下面的查询

 public static TypedQuery findAllStudentsOrderByColumn(String column, String orderType, int limitStart, int limitAmount) { EntityManager em = Programme.entityManager(); TypedQuery q = em.createQuery("SELECT o FROM Student AS o ORDER BY"+" "+column+" "+orderType, Student.class); q.setFirstResult(limitStart);//used to skip the first "N" elements form the result set, it indexes results form zero q.setMaxResults(limitAmount); return q; } 

我在上面的操作中设置的限额。 这个值是10。

好的,所以这里是基于JPA的部分答案(但我认为将它适应Hibernate应该是微不足道的)。 你应该能够做这样的事情来获取必要的对象:

 Query query = em.createQuery("select o from " + "Student"+ " as o order by o.id"); query.setFirstResult(start); query.setMaxResults(end - start); return query.getResultList(); 

对于计数,这样的事情应该这样做:

 Number count = (Number) em.createQuery("select count(id) from " + "Student").getSingleResult(); if (count == null) { count = Integer.valueOf(0); } return count.intValue(); 

当我有更多信息时会编辑。

首先,我发现1分钟内总共5000行的10行加载非常 。 我认为服务器代码而不是jqGrid在你的情况下的瓶颈。

第一个非常可疑的代码行是

 List countStudents = Student.findAllStudents(); 

您只需要获得学生人数 ,但似乎您获得了所有学生的所有属性,然后在接下来的两行中使用countStudents.size() 。 应该做的最大值是什么

 SELECT COUNT(*) FROM dbo.Students 

而不是这样,你可以做SELECT * FROM dbo.Students

如果您的代码需要1分钟,那么您可能在数据库或函数findAllStudentsOrderByColumn的实现中遇到严重问题。 可能你有一些代表实体模型或数据库模型的类。 如果性能太差,则必须仔细检查数据库访问的代码,或者考虑使用更直接的数据库访问权限,直接指定数据库查询。 我不是Java或Spring的开发人员,但我可以肯定地说,如果5000行的10行请求比1秒慢得多。

看起来您需要从包含id一个表中返回一些列。 所以你可以用SELECT来获取数据

 SELECT TOP(10) id, firstName, lastName, dateOfBirth, gender, maritalStatus FROM dbo.Students ORDER BY id 

获取第一页数据,如下所示

 WITH GetAll (id, firstName, lastName, dateOfBirth, gender, maritalStatus) AS ( SELECT id, firstName, lastName, dateOfBirth, gender, maritalStatus FROM dbo.Students ORDER BY id ), GetTop (id, firstName, lastName, dateOfBirth, gender, maritalStatus) AS ( SELECT TOP(20) * FROM GetAll -- skip 2 pages per 10 rows ), GetNext (id, firstName, lastName, dateOfBirth, gender, maritalStatus) AS ( SELECT TOP(10) a.* FROM GetAll AS a LEFT OUTER JOIN GetTop AS t ON t.id = a.id WHERE t.id IS NULL ) SELECT * FROM GetNext 

对于所有下一页。 我使用了公用表表达式(CTE)语法,但如果您的数据库不支持它,则可以使用子查询。

因为您允许按每列进行排序,所以应该在表中的每一列上创建INDEX,以提高排序性能。 (我认为Students表不会被修改,每秒有很多更改,因此索引不会降低表的性能)。

您应该考虑的另一件事是将序列化更改为JSON。 String.format("\"%s\", someString)是危险的。有些字符必须用\ _字符转义。我的意思是"\ 。 您应该这样做以使代码安全。 通常的做法是使用您的语言中存在的一些标准类进行序列化(请参阅此处或此处 )。

下一个提示是使用jsonReader: {cell: ""}并返回表单中行的数据

 ["%s", "%s", "%s", "%s", "%s", "%s"] 

代替

 {"id":"%s", "cell":["%s", "%s", "%s", "%s", "%s", "%s"]} 

您将不会发送两次id值,并且不会发送字符串"id" “cell”和其他一些不需要的字符('{‘,’:’,…)。

在客户端,您应该始终使用gridview: true jqGrid选项。 使用10行数据你不会看到严重的差异,因为jqGrid将非常快,但是有更多行,差异将非常明显。

最后一个建议:您应该使用formatter: 'date'并以ISO 8601格式发送日期:如2012-03-20