• Mybatis常用的OGNL表达式


    在Mybatis的动态SQL和${}形式的参数中都用到了OGNL表达式。

    Mybatis常用的OGNL表达式

    e1 or e2:或

    <if test="userEmail != null or userEmail == '1'">
    </if>
    
    • 1
    • 2

    e1 and e2:且

    <if test="userEmail != null and userEmail != ''">
    </if>
    
    • 1
    • 2

    e1 == e2 或e1 eq e2:相等

    <if test="userEmail == null and userEmail == ''">
    </if>
    
    • 1
    • 2

    e1 != e2 或 e1 neq e2:不等

    <if test="userEmail != null and userEmail != ''">
    </if>
    
    • 1
    • 2

    e1 lt e2:小于

    <if test="age lt 10">
    </if>
    
    • 1
    • 2

    e1 lte e2:小于等于

    e1 gt e2:大于

    e1 gte e2:大于等于

    e1 + e2(加),e1 - e2(减),e1 * e2(乘),e1/e2(除),e1%e2(余)

    !e或not e:非,取反

    e.method(args):调用对象方法

    <if test="list != null and list.size() > 0 ">
    		#{userEmail,jdbcType=VARCHAR},
    </if>
    
    • 1
    • 2
    • 3

    e.property:对象属性值

    <!-- 多接口参数的查询方法(@Param + javaBean方式) -->
      <select id="selectByUserIdAndEnabledUseBean" resultMap="BaseResultMap">
        select r.id, r.role_name, r.enabled, r.create_by, r.create_time, 
        u.user_name as "user.userName", u.user_email as "user.userEmail"
        from sys_user u 
        inner join sys_user_role ur on u.id = ur.user_id 
        inner join sys_role r on ur.role_id = r.id 
        where u.id = #{user.id} and r.enabled = #{role.enabled}
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    e1[e2]:按索引取值(List、数组和map)

    @class@method(args):调用类的静态方法

    <bind name="name" value="@ex.mybatis.rbac.mapper.UserMaperTest@setName()"/>
    
    • 1

    @class@field:调用类的静态字段值

    <bind name="name" value="@ex.mybatis.rbac.mapper.UserMaperTest@NAME"/>
    
    • 1

    MyBatis中什么地方可以使用OGNL

    下面这两处地方在MyBatis中处理的时候都是使用OGNL处理的。

    动态SQL表达式中

    示例1

    <select id="xxx" ...>
        select id,name,... from country
        <where>
            <if test="name != null and name != ''">
                name like concat('%', #{name}, '%')
            </if>
        </where>
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上面代码中test的值会使用OGNL计算结果。

    示例2

    <select id="xxx" ...>
        select id,name,... from country
        <bind name="nameLike" value="'%' + name + '%'"/>
        <where>
            <if test="name != null and name != ''">
                name like '${nameLike}'
            </if>
        </where>
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这里的value值会使用OGNL计算。

    注:对

    在通用Mapper中支持一种UUID的主键,在通用Mapper中的实现就是使用了标签,这个标签调用了一个静态方法,大概方法如下:

    <bind name="username_bind" value='@java.util.UUID@randomUUID().toString().replace("-", "")' />
    
    • 1

    这种方式虽然能自动调用静态方法,但是没法回写对应的属性值,因此使用时需要注意。

    ${param}参数中

    上面like的例子中使用下面这种方式最简单

    <select id="xxx" ...>
        select id,name,... from country
        <where>
            <if test="name != null and name != ''">
                name like '${'%' + name + '%'}'
            </if>
        </where>
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里注意写的是${‘%’ + name + ‘%’},而不是%${name}%,这两种方式的结果一样,但是处理过程不一样。

    在MyBatis中处理${}的时候,只是使用OGNL计算这个结果值,然后替换SQL中对应的${xxx},OGNL处理的只是${这里的表达式}。

    这里表达式可以是OGNL支持的所有表达式,可以写的很复杂,可以调用静态方法返回值,也可以调用静态的属性值。

    示例1:查询多个父级的所有的子级组织

    <select id="selectAllSubDeptByDeptIds" resultType="long">
        SELECT
            d.id
        FROM
            dept d
            INNER JOIN(
                SELECT * FROM (
                    (SELECT @ids :=
                            <!--将集合deptList使用 逗号 拼接起来, 此处使用foreach会查不出结果, 即使是使用了replace去掉了空格的情况下-->
                            '${@org.springframework.util.StringUtils@collectionToCommaDelimitedString(deptIdList)}'
                    ) a
                    , (SELECT @ids AS _ids ,
                              (SELECT @ids := GROUP_CONCAT(id) FROM dept WHERE FIND_IN_SET(parent_id, @ids)) AS cids
                       FROM
                            dept d
                       WHERE
                            @ids IS NOT NULL AND d.is_del = 0
                    ) b
                )
            ) T ON FIND_IN_SET(d.id, T.cids)
        WHERE
            d.is_del = 0
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    示例2:查询未被邀请的组织

    <select id="selectNoInvitedDepts" resultType="com.anbao.train.data.dto.dept.DeptTreeDto">
        SELECT
            d.id,
            d.name,
            d.parent_id,
            d.hospital_area_id
        FROM
            dept d
        WHERE
            d.hospital_area_id = #{hospitalAreaId}
            AND d.merchant_code = #{merchantCode}
            <if test="deptIds != null and deptIds.size() != 0">
                AND NOT FIND_IN_SET(d.id,
                        (SELECT
                            group_concat( _ids )
                         FROM
                            (
                                ( SELECT @ids :=
                                    '${@org.springframework.util.StringUtils@collectionToCommaDelimitedString(deptIds)}'
                                ) a,
                                (
                                    SELECT
                                        @ids AS _ids,
                                        (
                                        SELECT
                                            @ids := GROUP_CONCAT( id )
                                        FROM
                                            dept
                                        WHERE
                                            FIND_IN_SET( parent_id, @ids )) AS cids
                                    FROM
                                        dept
                                    WHERE
                                        @ids IS NOT NULL
                                ) b
                            )
                        )
                    )
            </if>
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    示例3:删除多个父级所有的子级组织

    <delete id="deleteCourseInvitationSubDepts">
        DELETE
        FROM
            course_invitation ci
        WHERE
            ci.course_id = #{courseId}
            AND FIND_IN_SET (ci.dept_id,
                      (
                         SELECT
                            group_concat( cids )
                         FROM (
                                ( SELECT @ids :=
                                    '${@org.springframework.util.StringUtils@collectionToCommaDelimitedString(deptIdList)}'
                                ) a,
                                (SELECT
                                    @ids AS _ids,
                                    (SELECT
                                        @ids := GROUP_CONCAT( id )
                                    FROM
                                        dept
                                    WHERE
                                        FIND_IN_SET( parent_id, @ids )
                                    ) AS cids
                                FROM
                                    dept
                                WHERE
                                    @ids IS NOT NULL
                                ) b
                              )
                      )
                )
    </delete>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    示例4:使用OGNL实现单表的分表功能

    分表这个功能是通用Mapper中的新功能,允许在运行的时候指定一个表名,通过指定的表名对表进行操作。这个功能实现就是使用了OGNL。

    首先并不是所有的表都需要该功能,因此定义了一个接口,当参数(接口方法只有实体类一个参数)对象继承该接口的时候,就允许使用动态表名。

    public interface IDynamicTableName {
     
        /**
         * 获取动态表名 - 只要有返回值,不是null和'',就会用返回值作为表名
         *
         * @return
         */
        String getDynamicTableName();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    然后在XML中写表名的时候使用:

    <if test="@tk.mybatis.mapper.util.OGNL@isDynamicParameter(_parameter) 
                and dynamicTableName != null 
                and dynamicTableName != ''">
        ${dynamicTableName}
    </if>
    <if test="@tk.mybatis.mapper.util.OGNL@isNotDynamicParameter(_parameter) 
                or dynamicTableName == null 
                or dynamicTableName == ''">
        defaultTableName
    </if>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    由于我需要判断_parameter是否继承了IDynamicTableName接口,简单的写法已经无法实现,所以使用了静态方法,这两个方法如下:

    /**
     * 判断参数是否支持动态表名
     *
     * @param parameter
     * @return true支持,false不支持
     */
    public static boolean isDynamicParameter(Object parameter) {
        if (parameter != null && parameter instanceof IDynamicTableName) {
            return true;
        }
        return false;
    }
     
    /**
     * 判断参数是否b支持动态表名
     *
     * @param parameter
     * @return true不支持,false支持
     */
    public static boolean isNotDynamicParameter(Object parameter) {
        return !isDynamicParameter(parameter);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    根据判断的结果来选择使用那个表名。

    另外注意XML判断中有一个dynamicTableName,这个参数是根据getDynamicTableName方法得到的,MyBatis使用属性对应的getter方法来获取值,不是根据field来获取值。

  • 相关阅读:
    基于Vivado软件实现电梯控制器仿真设计
    CUDA和cudnn详细安装过程【通用win】
    一条Sql的执行过程
    历时7天,四名学生将《水浒传》搬到线上!
    Spring MVC应用的开发步骤
    元分析 | 大脑同伦共激活的性别差异
    【Proteus仿真】【STM32单片机】智能语音家居陪护机器人
    冯诺依曼体系结构与操作系统
    Langchain-Chatchat项目:4.1-P-Tuning v2实现过程
    一种对数据库友好的GUID的变种使用方法
  • 原文地址:https://blog.csdn.net/qq_16992475/article/details/126068875