Могу ли я реализовать отложенную загрузку с помощью jqGrid? - PullRequest
2 голосов
/ 20 марта 2012

У меня есть сетка с более чем 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.

Ответы [ 2 ]

3 голосов
/ 20 марта 2012

Прежде всего я нахожу, что загрузка 10 строк из общего количества 5000 за 1 минуту составляет ЧРЕЗВЫЧАЙНО медленно .Я думаю, что код сервера, а не jqGrid в узком месте в вашем случае.

Первая очень подозрительная строка вашего кода

List<Student> countStudents = Student.findAllStudents();

Вам необходимо получитьтолько число учеников, но кажется, что вы получаете все свойства всех учеников и затем используете countStudents.size() в двух следующих строках.Максимум, что должно быть сделано, это что-то вроде

SELECT COUNT(*) FROM dbo.Students

Вместо этого это означает, что вы делаете SELECT * FROM dbo.Students.

Может случиться так, что у вас возникнут серьезные проблемы в базе данных или при реализациифункция findAllStudentsOrderByColumn если ваш код займет 1 минуту.Возможно, у вас есть несколько классов, которые представляют модель сущности или модель базы данных.Если у вас такая плохая производительность, вам нужно тщательно изучить код, который делает доступ к базе данных, или рассмотреть возможность использования более прямого доступа к базе данных, где вы можете указать запросы к базе данных напрямую.Я не Java или Spring разработчик, но я могу с уверенностью сказать, что если запрос из 10 строк из 5000 получает больше как 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) , но вы можете использовать подзапросы, если ваша база данных не поддерживает его.

Поскольку вы разрешаете сортировать по каждому столбцу, вы должны создавать INDEXesна каждом столбце в таблице, чтобы улучшить производительность сортировки.(Я думаю, что таблица «Студенты» не будет изменяться с большим количеством изменений в секунду, поэтому индексы не уменьшат производительность таблицы).

Еще одна вещь, которую вы должны учитывать, - это изменить сериализациюв JSON.Использование String.format("\"%s\", someString) опасно.Есть несколько символов, которые должны быть экранированы символом \.Я имею в виду " и \.Вы должны сделать это, чтобы сделать код безопасным.Обычной практикой является использование некоторых стандартных классов, существующих на вашем языке, для сериализации (см., Например, здесь или здесь ).

Следующий совет - использовать jsonReader: {cell: ""} и вернуть данные для строки в виде

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

вместо

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

Вы не будете отправлять id значение дважды и не будете отправлять строки "id" "ячейка" и некоторые другие ненужные символы ('{', ':', ...).

На стороне клиента вы должны всегда использовать gridview: true параметр jqGrid.С 10 строками данных вы не увидите серьезных различий, потому что jqGrid будет очень быстрым, но с большим количеством строк разница будет очень четкой.

Последнее предложение: вы должны использовать formatter: 'date' и отправитьдата в формате ISO 8601 : например, 2012-03-20.

2 голосов
/ 20 марта 2012

Хорошо, вот частичный ответ, основанный на 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();

Будет редактировать, когда у меня естьбольше информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...