javapostgresqlspring-mvcmybatisxmlmapper

myBatis xml mapper filer in use with Java interface - dynamic SQL query


I have problem. I didnt create MyBatis config. I heard it may work without it. I have Java interface called for example: InterfaceDAO.java and myBatis mapper InterfaceDAO.xml

InterfaceDAO.java :

@Mapper
public interface InterfaceDAO extends ApiConsumerDAO, ServiceDAO {

@Select("SELECT * FROM interface WHERE id = #{interfaceId}")
@Results({
        @Result(property = "id", column = "id"),
        @Result(property = "date", column = "date"),
        @Result(property = "apiConsumer", column = "api_consumer", one = @One(select = "getApiConsumer")),
        @Result(property = "service", column = "service", one = @One(select = "getService")),
        @Result(property = "counterStatus", column = "counter_status"),
        @Result(property = "ratingProcessId", column = "rating_process_id"),
        @Result(property = "value", column = "value"),
        @Result(property = "createdDate", column = "created_date"),
        @Result(property = "modifiedDate", column = "modified_date")
})
InterfaceObject getInterfaceDAO(@Param("interfaceId") Integer interfaceId);


List<InterfaceObject > getInterfaceDAOList(@Param("apiConsumerIdsList") List<Integer> apiConsumerIdsList,
                                       @Param("serviceIdsList") List<Integer> serviceIdsList,
                                       @Param("dateFrom") Date dateFrom,
                                       @Param("dateTo") Date dateTo,
                                       @Param("status") InterfaceDAO.Status status);
}

InterfaceDAO.xml :

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="pl.net.manager.dao.InterfaceDAO">
    <select id="getInterfaceDAOList" parameterType="map" resultType="List">
        SELECT * FROM interface WHERE
        <if test="apiConsumerIdsList != null">
            #{apiConsumerIdsList} IS NULL OR api_consumer IN (#{apiConsumerIdsList,jdbcType=ARRAY})
        </if>
        <if test="serviceIdsList != null">
            #{serviceIdsList} IS NULL OR service IN (#{serviceIdsList,jdbcType=ARRAY})
        </if>
        <if test="status != null">
            #{status} IS NULL OR status IN (#{status,jdbcType=ARRAY})
        </if>
        <if test="dateFrom != null">
            #{dateFrom} IS NULL OR date &gt;= #{dateFrom,jdbcType=DATE}
        </if>
        <if test="dateTo != null">
            #{dateTo} IS NULL OR date &lt;= (#{dateTo,jdbcType=DATE})
        </if>
    </select>
</mapper>

And so the first method example called: getInterfaceDAO is working propely. But The second called: getInterfaceDAOList is more complicated and didnt work the same way the first one. That is why I want this particular method to use the xml mapper to gain data I want. The income arguments can be null or there can be several values in list.

Have you met with such a problem, and do you knows some best ways to solve this? This is my first contact with this.

I am using MyBatis and Postgres DB.


Solution

  • Firstly you can remove #{apiConsumerIdsList} IS NULL and similar occurances because you already checking for != null in your if condition and that should suffice.

    Secondly, for the IN clause you would have to use the foreach construct as shown below:

    <foreach item="item" index="index" collection="apiConsumerIdsList" 
        open="(" separator="," close=")">
      #{item}
    </foreach>
    

    The above is applicable to all the IN clauses.

    And the expression #{dateFrom,jdbcType=DATE} can simply be written as #{dateFrom:DATE}

    Then coming to the WHERE clause, if multiple of the if conditions satisfy, then your WHERE clause will break because of the absence of AND, for that you can use <where> tag something like

    <where>
        <if test="apiConsumerIdsList != null">
        api_consumer IN <foreach item="item" collection="apiConsumerIdsList" 
                open="(" separator="," close=")">
              #{item}
            </foreach>
        </if>
        <if test="serviceIdsList != null">
            AND service IN <foreach item="item" collection="serviceIdsList" 
                    open="(" separator="," close=")">
                  #{item}
                </foreach>(#{serviceIdsList,jdbcType=ARRAY})
        </if>
        <if test="status != null">
            AND status IN <foreach item="item" collection="status" 
                    open="(" separator="," close=")">
                  #{item}
                </foreach>
        </if>
        <if test="dateFrom != null">
            AND date &gt;= #{dateFrom:DATE}
        </if>
        <if test="dateTo != null">
            AND date &lt;= (#{dateTo:DATE})
        </if>
    </where>