Extremely dynamic queries with MyBatis for remote grid filtering/pagination/sorting

StackOverflow https://stackoverflow.com/questions/9488546

  •  14-11-2019
  •  | 
  •  

Question

A project I'm working on makes heavy use of the ExtJS framework. We have a lot of data to display and we do so via grids, which all have a standard set of paging, sorting, and filtering features.

Currently, our backend is in PHP and we are using straight SQL. I wrote a SQL wrapper in PHP that would accept a query, a list of filters, sort info, and page info and output a query that had the appropriate WHERE, ORDER BY, and pagination features by using the original query as a subquery. I should note that our project is tied to Oracle.

Filters can come in the form of comparisons (=, <, <=, >=, >, IS NULL) or lists ( IN () ) and sorting is simply a single column with a direction. Pagination is start and end rownumbers.

Longish story short, we are moving toward a java-based architecture using Spring and MyBatis. I'm having a hard time figuring out how to implement the same functionality using MyBatis in an easy way. The nice thing about the wrapper was that we only had to write our base query once and then it would morph into whatever query the grid needed. Since we are talking about potentially tens of thousands of records and we need pagination, pulling things back to the server and doing java-based filtering/sorting isn't really an option.

Has anyone solved this (or a similar) problem before? I've seen the Dynamic SQL capabilities of MyBatis (briefly) but it doesn't seem to offer quite the flexibility and power that I need. Am I wrong?

Any guidance from seasoned MyBatis users would be greatly appreciated.

I should note that we are exploratory right now and that using an ORM isn't entirely off the table. Is this something more easily accomplished using, say, Hibernate?

Was it helpful?

Solution

I am doing almost exactly the same (just using Guice instead of Spring) plus my query is hierarchical (results shown in a tree table) which complicates the matter very much.

I think MyBatis can do this nicely. For the dynamic part of the query however I would set aside MyBatis amd implement it the same way you probably did with PHP: Generate the WHERE and ORDER BY parts of your statement in Java.

Define a mybatis result map for your base query and the base query itself in a reusable snippet, then use String substitution directly in the mapping file:

Something like this:

<resultMap id="TaskMap" type="de.foobar.dtos.TaskDto">
    <id column="id" property="id"/>
    <result column="description" property="description"/>
    ...
</resultMap>

<sql id="baseQuery">
    select id, description from tasks
</sql>

<select id="selectSingle" resultMap="Task2Map">
    select bq.*
    from (
            <include refid="baseQuery"/>
         ) bq
    where bq.id = #{id}
</select>

<select id="selectAll" resultMap="Task2Map">
    select bq.*
    from (
            <include refid="baseQuery"/>
         ) bq
    where ${filterClause}
    order by ${orderByClause}
</select>

For the pagination you will have to wrap another subquery in to use the strange oracle rownum construct (but you probably do so already anyway).

Also of course the usual warning applies: The ${} syntax in MyBatis is doing string substition (rather than parameters of a prepared statement), so be careful in sanitizing user input to avoid sql injection.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top