Spring Data JPA по запросу с выбором нескольких таблиц и псевдонимом нумерации страниц для проблемы заказа - PullRequest
0 голосов
/ 26 сентября 2019

В этом и заключается подвох: мы создали веб-приложение, использующее Spring MVC, которое подключалось к базе данных Oracle 12c, используя Hibernate и Hikari в качестве пула соединений.

мы используем стиль запросов HQL для выбора данных с помощью Spring Data JPA.Мы используем select from multiple tables запрос для серверной части.

Вот часть внутреннего хранилища:

@Query(value = "SELECT t1.p1 as p1, " +
            "       t2.p2 as p2, " +
            "       t3.p3 as p3, " +
            "       t4.p4 as p4, " +
            "from Model1 t1, " +
            "     Model2 t2, " +
            "     Model3 t3, " +
            "     Model4 t4 " +
            "where t1.p1 = t2.p1 " +
            "   and t2.p2 = t2.p2 " +
            "   and t3.p3 = t3.p3 " +
            "   and (p1 = ?1 or ?1 is null) " +
            "   and (p2 = ?2 or ?2 is null) " +
            "   and (p3 = ?3 or ?3 is null) " +
            "   and (p4 = ?4 or ?4 is null) ")
    fun finder(
            @Param("p1") p1: String?,
            @Param("p2") p2: String?,
            @Param("p3") p3: String?,
            @Param("p4") p4: String?,
            pageable: Pageable
    ): Page<Array<Any>>

, как вы можете видеть, мы используем Spring Data Pagination.

сейчасвплоть до проблемы.

для отображения данных, на внешней стороне мы используем jQuery Datatable и HTML.

внешний код на стороне HTML выглядит следующим образом:

<div class="col-xs-12">
                            <div class="box box-danger">
                                <div class="box-body">
                                    <table id="tnTable" class="table table-bordered table-striped">
                                        <thead>
                                            <tr>
                                                <th>P1</th>
                                                <th>P2</th>
                                                <th>P3</th>
                                                <th>P4</th>
                                                <th>P5</th>
                                                <
                                            </tr>
                                        </thead>
                                        <tbody></tbody>
                                    </table>
                                </div>
                            </div>
                        </div>

javascript code:

_initTable: function () {
                            var self = this;

                            _table = $("#tnTable").DataTable({
                                deferLoading: 0,
                                serverSide: true,
                                pageLength: 25,
                                autoWidth: false,
                                searching: false,
                                ajax: {
                                    "url": "/request/ajax",
                                    "data": function(data) {
                                        data.p1 = $('#filter1').val();
                                        data.p2 = $('#filter2').val();
                                        data.p3 = $('#filter3').val();
                                        data.p4 = $('#filter4').val();
                                    }
                                },
                                columns : [
                                    { data: 'p1', orderable: false},
                                    { data: 'p2', orderable: false},
                                    { data: 'p3', orderable: false},
                                    { data: 'p4', orderable: false},
                                    { data: 'p5', orderable: false},
                                    { data: 'p6', orderable: false},
                                    { data: 'p7'}
                                ],
                                order: [[ 6, "desc" ]],
                                drawCallback: function(settings) {
                                    $.unblockUI();
                                }
                            });

контроллер на бэкэнд-коде:

@RequestMapping(value = ["/ajax"], method = [RequestMethod.GET])
    fun ajax(request: HttpServletRequest): DataTableModel {

        // begin filter request
        val p1 = request.getParameter("p1")
        val p2 = request.getParameter("p2")
        val p3 = request.getParameter("p3")
        val p4 = request.getParameter("p4")
        // end filter request

        val pageSize = Integer.valueOf(request.getParameter("length"))
        val page = Integer.valueOf(request.getParameter("start")) / pageSize
        var sortBy = "p1"
        val order = request.getParameter("order[0][dir]")
        when (Integer.valueOf(request.getParameter("order[0][column]"))) {
            0 -> sortBy = "t1.p1"
            6 -> sortBy = "t4.p6"
        }
        val pageable = PageRequest.of(page, pageSize, if (order.equals("asc", ignoreCase = true)) Sort.Direction.ASC else Sort.Direction.DESC, sortBy)
        val data = service.finder(
                p1,
                p2,
                p3,
                p4,
        )
        val modelList: MutableList<SomeModel> = ArrayList()
        val draw = Integer.valueOf(request.getParameter("draw"))

        for (o in data) {
            val model = SomeModel(0[0].toString(), 0[1].toString(), (etc..))
            modelList.add(model)
        }

        return DataTableModel(draw, data.totalElements, data.totalElements.toInt(), data)
    }

service слой просто проходит через запрос к уровню хранилища, поэтому я подумал, что его код нездесь неважно.

оглядываясь на код, по частям javascript ясно, что индекс столбца с номером 6 был отправлен в качестве значения порядка, можно предположить, что это значение должно быть сопоставлено с таблицей t4 столбца.p6.

, поэтому мы предполагаем, что это будет переведено с помощью гибернации и сопоставленной корреляции с предварительно созданным запросом, поскольку мы добавили префикс для упорядочивания деталей здесь:

when (Integer.valueOf(request.getParameter("order[0][column]"))) {
            0 -> sortBy = "t1.p1"
            6 -> sortBy = "t4.p6"
        }

, но чтослучилось здесь, мы получилиследующая ошибка из Hibernate:

org.hibernate.QueryException: could not resolve property: t4.p6 of: com.example.domain.Model1

затем мы попытались переименовать передаваемое значение порядка следующим образом:

when (Integer.valueOf(request.getParameter("order[0][column]"))) {
            0 -> sortBy = "p1"
            6 -> sortBy = "p6"
        }

без удачи.

и так посленекоторые копания об ошибке, из того, что мы понимаем здесь, это попытка перехода в спящий режим для сопоставления значения порядка поля p6 , которое должно быть членом поля класса Model4 , с классом Model1, которого там нет из-за появления порядка выбора здесь, в части внутреннего хранилища, Model1 находится в первом списке:

"from Model1 t1, " +
            "     Model2 t2, " +
            "     Model3 t3, " +
            "     Model4 t4 " +

, потому что, однако, мы играем с частью поля заказа на стороне контроллера, из каждого полячлен за пределами Model1, он просто выдает ту же ошибку.

НО , если мы изменим внешний вид порядка в части хранилища бэкэнда без изменений по сравнению с другими частями предыдущего кода, как это:

"from Model4 t4, " +
            "     Model2 t2, " +
            "     Model3 t3, " +
            "     Model1 t1 " +

Нет ошибок.он просто сопоставлен правильно, поэтому из-за этих обстоятельств появления порядка упорядочения таблиц в запросе выбора должны быть составлены так, чтобы соответствовать элементу значения порядка, который сопоставляется с той таблицей, впервые появившейся в операторе выбора таблицы.

мы имеемуже пытался использовать необработанный запрос в качестве замены для стиля HQL, но, насколько мы можем судить, ошибка и проблема остаются.

Это известная проблема?Как я могу преодолеть это, если это возможно?

Любой указатель высоко ценится, спасибо.

...