我有一个包含超过 5000 条数据记录的网格。这些数据每天都在增长。当我用网格加载页面时,网格显示数据需要将近一分钟,我必须一次显示 10 行。
是否可以用这个 jqGrid 实现延迟加载?
这是我生成 JSON 字符串的操作:
@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<Student> students = Student.findAllStudentsOrderByColumn(column,orderType,limitStart,limitAmount).getResultList();
List<Student> 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,
/* <![CDATA[ */
onSelectRow: function(id){
if((lastsel != 0)&&(id!==lastsel)){
$("#studentGrid").jqGrid('collapseSubGridRow', lastsel);
}
lastsel=id;
}/* ]]> */
});
$("#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<tt.edu.sbcs.model.Student> findAllStudentsOrderByColumn(String column, String orderType, int limitStart, int limitAmount) {
EntityManager em = Programme.entityManager();
TypedQuery<Student> 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。
最佳答案
首先,我发现在 1 分钟内加载 5000 行中的 10 行非常慢。我认为服务器代码而不是 jqGrid 在你的情况下是瓶颈。
您的代码的第一行非常可疑是
List<Student> 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
所有下一页。我用了common table expression (CTE)语法,但如果您的数据库不支持,您可以使用子查询。
因为您允许按每一列进行排序,所以您应该在表中的每一列上创建索引以提高排序性能。 (我认为 Students 表不会被修改,每秒有很多变化,所以索引不会降低表的性能)。
您应该考虑的另一件事是将序列化更改为 JSON。 String.format("\"%s\", someString)
的用法是危险的。有些字符必须使用 \
字符进行转义。我的意思是 "
和 \
。您应该这样做以使代码安全。通常的做法是使用您的语言中存在的一些标准类进行序列化(例如,参见 here 或 here)。
下一个技巧是使用 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
。
关于java - 我可以用 jqGrid 实现延迟加载吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9790122/