myBatis --(5)动态sql

动态sql是myBatis中相当有用的一个知识点,总体来说,动态sql有如下几类:

1>if语句(简单的条件判断)

2>choose(相当于case when),即C语言中的switth

3>trim(对包含的内容加上prefix(前缀)、或者suffix(后缀)等)

4>where(简化SQL语句中where条件判断)

5>set(用于 更新时设置)

6>foreach(实现myBatis in语句查询时有用)

如下例子均是普通sql操作的例子,如果采用oracle中的存储过程时,请直接看后面讲解。

一、if语句

使用环境举例:查询招聘列表,根据地点、薪资、工作经验等筛选条件进行筛选。

分析:这个时候,条件是动态的,可以全部选择,也可以只选择一部分。

动态SQL语句如下

    <select id="getMyJobList" parameterType="com.zhiji.caren.VO.AttentionMyParams"
        resultMap="BaseResultMapJobList">

        SELECT
        tall.LOCATION_ID,
        tall.LOCATION_NAME,
        tall.JOB_ID,
        tall.JOB_NAME,
        tall.NEGOTIABLE_FLAG,
        tall.SALARY_MAX,
        tall.SALARY_MIN,
        tall.ADD_TIME,
        tall.ENTERPRISE_ID,
        tall.ENTERPRISE_NAME,
        tall.ENTERPRISE_LOGO,
        tall.WORK_YEARS_ID,
        tall.WORK_YEARS_INFO,
        IFNULL( tujf.FOCUS_FLAG,0) as
        flag
        FROM
        (SELECT
        tj.JOB_ID,
        tj.LOCATION_ID,
        tl.LOCATION_NAME,
        tj.JOB_NAME,
        tj.NEGOTIABLE_FLAG,
        tj.SALARY_MAX,
        tj.SALARY_MIN,
        tj.ADD_TIME,
        tj.ENTERPRISE_ID,
        te.ENTERPRISE_NAME,
        te.ENTERPRISE_LOGO,
        twy.WORK_YEARS_ID,
        twy.WORK_YEARS_INFO,
        '' AS flag
        FROM
        t_job
        tj,t_location tl,t_enterprise te,t_hr th,t_work_years
        twy,t_job_category tjc,t_job_type tjt
        WHERE tj.LOCATION_ID =
        tl.LOCATION_ID
        AND tl.LOCATION_LEVEL = 2
        AND tl.USE_FLAG = 1
        AND
        tj.ENTERPRISE_ID = te.ENTERPRISE_ID
        AND te.USE_FLAG = 1
        AND tj.HR_ID =
        th.HR_ID
        AND th.USE_FLAG = 1
        AND tj.WORK_YEARS_ID = twy.WORK_YEARS_ID
        AND tj.JOB_CATEGORY_ID = tjc.JOB_CATEGORY_ID
        AND tjc.USE_FLAG = 1
        AND
        tj.JOB_TYPE_ID = tjt.JOB_TYPE_ID
        AND tjt.USE_FLAG = 1
        <if test="jobCategoryId != null">
            AND
            tjc.JOB_CATEGORY_ID = #{jobCategoryId}
        </if>
        <if test="locationId != null">
            AND
            tl.LOCATION_ID = #{locationId}
        </if>
        <if test="workYearId != null">
            AND
            twy.WORK_YEARS_ID = #{workYearId}
        </if>
        <if test="jobTypeId != null">
            AND
            tjt.JOB_TYPE_ID = #{jobTypeId}
        </if>
        <if test="lastTime != null">
            AND
            tj.ADD_TIME &lt;= #{lastTime}
        </if>
        GROUP BY
        tj.JOB_ID
        ORDER BY
        tj.ADD_TIME DESC) tall
        left join
        (select JOB_ID
        as
        FOCUS_JOB_ID,'1' as FOCUS_FLAG from
        t_user_job_focus where
        user_id =
        #{userId} and TYPE = '01') tujf
        on
        tall.JOB_ID = tujf.FOCUS_JOB_ID
        LIMIT
        #{pageIndex}

    </select>

备注:很明显,上面的if判断可以满足需求,只有当输入的条件不为空时(即选择了该筛选条件),SQL查询条件才带上这个筛选条件;否则,不带上这个筛选条件(即没有选择这个筛选条件)。

二、choose

它相当于C语言中的switch case。

适用场景:多选一的时候。

choose标签是按照顺序判断其内部when标签中的test条件是否成立,如果一旦成立,则choose语句结束;当choose中所有when条件都不满足时,则执行otherwise中的sql。

如上例子:筛选条件由多选变成单选

动态SQL语句如下

<select id="getMyJobList" parameterType="com.zhiji.caren.VO.AttentionMyParams"
        resultMap="BaseResultMapJobList">

        SELECT
        tall.LOCATION_ID,
        tall.LOCATION_NAME,
        tall.JOB_ID,
        tall.JOB_NAME,
        tall.NEGOTIABLE_FLAG,
        tall.SALARY_MAX,
        tall.SALARY_MIN,
        tall.ADD_TIME,
        tall.ENTERPRISE_ID,
        tall.ENTERPRISE_NAME,
        tall.ENTERPRISE_LOGO,
        tall.WORK_YEARS_ID,
        tall.WORK_YEARS_INFO,
        IFNULL( tujf.FOCUS_FLAG,0) as
        flag
        FROM
        (SELECT
        tj.JOB_ID,
        tj.LOCATION_ID,
        tl.LOCATION_NAME,
        tj.JOB_NAME,
        tj.NEGOTIABLE_FLAG,
        tj.SALARY_MAX,
        tj.SALARY_MIN,
        tj.ADD_TIME,
        tj.ENTERPRISE_ID,
        te.ENTERPRISE_NAME,
        te.ENTERPRISE_LOGO,
        twy.WORK_YEARS_ID,
        twy.WORK_YEARS_INFO,
        '' AS flag
        FROM
        t_job
        tj,t_location tl,t_enterprise te,t_hr th,t_work_years
        twy,t_job_category tjc,t_job_type tjt
        WHERE tj.LOCATION_ID =
        tl.LOCATION_ID
        AND tl.LOCATION_LEVEL = 2
        AND tl.USE_FLAG = 1
        AND
        tj.ENTERPRISE_ID = te.ENTERPRISE_ID
        AND te.USE_FLAG = 1
        AND tj.HR_ID =
        th.HR_ID
        AND th.USE_FLAG = 1
        AND tj.WORK_YEARS_ID = twy.WORK_YEARS_ID
        AND tj.JOB_CATEGORY_ID = tjc.JOB_CATEGORY_ID
        AND tjc.USE_FLAG = 1
        AND
        tj.JOB_TYPE_ID = tjt.JOB_TYPE_ID
        AND tjt.USE_FLAG = 1
        <choose>
        <when test="jobCategoryId != null">
            AND
            tjc.JOB_CATEGORY_ID = #{jobCategoryId}
        </when>
        <when test="locationId != null">
            AND
            tl.LOCATION_ID = #{locationId}
        </when>
        <when test="workYearId != null">
            AND
            twy.WORK_YEARS_ID = #{workYearId}
        </when>
        <when test="jobTypeId != null">
            AND
            tjt.JOB_TYPE_ID = #{jobTypeId}
        </when>
        <when test="lastTime != null">
            AND
            tj.ADD_TIME &lt;= #{lastTime}
        </when>
        <otherwise>
            AND
                1=1
        </otherwise>
        </choose>        
        GROUP BY
        tj.JOB_ID
        ORDER BY
        tj.ADD_TIME DESC) tall
        left join
        (select JOB_ID
        as
        FOCUS_JOB_ID,'1' as FOCUS_FLAG from
        t_user_job_focus where
        user_id =
        #{userId} and TYPE = '01') tujf
        on
        tall.JOB_ID = tujf.FOCUS_JOB_ID
        LIMIT
        #{pageIndex}

    </select>

说明:上述的SQL语句完成 筛选条件 多选一的时候。即筛选条件始终是只能选择一个或者不选。

三、trim

这个一般用得很少,我举一段用代码生成器生成的例子,如下

    <insert id="insertSelective" parameterType="com.zhiji.caren.model.Job">
        insert into t_job
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="jobId != null">
                JOB_ID,
            </if>
            <if test="jobName != null">
                JOB_NAME,
            </if>
            <if test="jobTypeId != null">
                JOB_TYPE_ID,
            </if>
            <if test="jobDepartment != null">
                JOB_DEPARTMENT,
            </if>
            <if test="enterpriseId != null">
                ENTERPRISE_ID,
            </if>
            <if test="jobCategoryId != null">
                JOB_CATEGORY_ID,
            </if>
            <if test="salaryMin != null">
                SALARY_MIN,
            </if>
            <if test="salaryMax != null">
                SALARY_MAX,
            </if>
            <if test="locationId != null">
                LOCATION_ID,
            </if>
            <if test="hrId != null">
                HR_ID,
            </if>
            <if test="workYearsId != null">
                WORK_YEARS_ID,
            </if>
            <if test="eduRequirementId != null">
                EDU_REQUIREMENT_ID,
            </if>
            <if test="jobDescription != null">
                JOB_DESCRIPTION,
            </if>
            <if test="jobAddress != null">
                JOB_ADDRESS,
            </if>
            <if test="auditFlag != null">
                AUDIT_FLAG,
            </if>
            <if test="stikyFlag != null">
                STIKY_FLAG,
            </if>
            <if test="negotiableFlag != null">
                NEGOTIABLE_FLAG,
            </if>
            <if test="hrInfoFlag != null">
                HR_INFO_FLAG,
            </if>
            <if test="useFlag != null">
                USE_FLAG,
            </if>
            <if test="validTime != null">
                VALID_TIME,
            </if>
            <if test="updUserId != null">
                UPD_USER_ID,
            </if>
            <if test="addTime != null">
                ADD_TIME,
            </if>
            <if test="updTime != null">
                UPD_TIME,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="jobId != null">
                #{jobId,jdbcType=INTEGER},
            </if>
            <if test="jobName != null">
                #{jobName,jdbcType=VARCHAR},
            </if>
            <if test="jobTypeId != null">
                #{jobTypeId,jdbcType=INTEGER},
            </if>
            <if test="jobDepartment != null">
                #{jobDepartment,jdbcType=VARCHAR},
            </if>
            <if test="enterpriseId != null">
                #{enterpriseId,jdbcType=INTEGER},
            </if>
            <if test="jobCategoryId != null">
                #{jobCategoryId,jdbcType=INTEGER},
            </if>
            <if test="salaryMin != null">
                #{salaryMin,jdbcType=INTEGER},
            </if>
            <if test="salaryMax != null">
                #{salaryMax,jdbcType=INTEGER},
            </if>
            <if test="locationId != null">
                #{locationId,jdbcType=INTEGER},
            </if>
            <if test="hrId != null">
                #{hrId,jdbcType=INTEGER},
            </if>
            <if test="workYearsId != null">
                #{workYearsId,jdbcType=INTEGER},
            </if>
            <if test="eduRequirementId != null">
                #{eduRequirementId,jdbcType=INTEGER},
            </if>
            <if test="jobDescription != null">
                #{jobDescription,jdbcType=VARCHAR},
            </if>
            <if test="jobAddress != null">
                #{jobAddress,jdbcType=VARCHAR},
            </if>
            <if test="auditFlag != null">
                #{auditFlag,jdbcType=CHAR},
            </if>
            <if test="stikyFlag != null">
                #{stikyFlag,jdbcType=INTEGER},
            </if>
            <if test="negotiableFlag != null">
                #{negotiableFlag,jdbcType=INTEGER},
            </if>
            <if test="hrInfoFlag != null">
                #{hrInfoFlag,jdbcType=INTEGER},
            </if>
            <if test="useFlag != null">
                #{useFlag,jdbcType=INTEGER},
            </if>
            <if test="validTime != null">
                #{validTime,jdbcType=CHAR},
            </if>
            <if test="updUserId != null">
                #{updUserId,jdbcType=INTEGER},
            </if>
            <if test="addTime != null">
                #{addTime,jdbcType=CHAR},
            </if>
            <if test="updTime != null">
                #{updTime,jdbcType=CHAR},
            </if>
        </trim>
    </insert>

上述是一条insert语句,去掉动态标签部分,学过SQL的人都应该看得懂。

这段代码<trim prefix="(" suffix=")" suffixOverrides=",">解释如下:

从<trim prefix="(" suffix=")" suffixOverrides=",">开始,如下那段代码后缀遇到","时,将那段代码用()括起来,同时,去掉最后的那个","号。

中间这段代码<trim prefix="values (" suffix=")" suffixOverrides=",">解释如下:

从<trim prefix="values (" suffix=")" suffixOverrides=",">开始,如下那段代码后缀遇到","时,那段代码的前面加上 values (,后面用 ")"代替","。

四、where

直接看例子

    <select id="getMyJobListPart" parameterType="com.zhiji.caren.VO.AttentionMyParams"
        resultMap="BaseResultMapJobList">
    
        SELECT
        tallTwo.JOB_ID,
        tallTwo.LOCATION_ID,
        tallTwo.LOCATION_NAME,
        tallTwo.JOB_NAME,
        tallTwo.NEGOTIABLE_FLAG,
        tallTwo.SALARY_MAX,
        tallTwo.SALARY_MIN,
        tallTwo.ADD_TIME,
        tallTwo.ENTERPRISE_ID,
        tallTwo.ENTERPRISE_NAME,
        tallTwo.ENTERPRISE_LOGO,
        tallTwo.WORK_YEARS_ID,
        tallTwo.WORK_YEARS_INFO,
        tallTwo.HR_ID,
        tallTwo.JOB_CATEGORY_ID,
        IFNULL( tujf.FOCUS_FLAG,0) as flag
        FROM
        (SELECT
        tall.JOB_ID,
        tall.LOCATION_ID,
        tl.LOCATION_NAME,
        tall.JOB_NAME,
        tall.NEGOTIABLE_FLAG,
        tall.SALARY_MAX,
        tall.SALARY_MIN,
        tall.ADD_TIME,
        tall.ENTERPRISE_ID,
        te.ENTERPRISE_NAME,
        te.ENTERPRISE_LOGO,
        tall.WORK_YEARS_ID,
        twy.WORK_YEARS_INFO,
        tall.HR_ID,
        tall.JOB_CATEGORY_ID,
        tall.JOB_TYPE_ID
        FROM
        (
        SELECT
        tj.JOB_ID,
        tj.LOCATION_ID,
        tj.JOB_NAME,
        tj.NEGOTIABLE_FLAG,
        tj.SALARY_MAX,
        tj.SALARY_MIN,
        tj.ADD_TIME,
        tj.ENTERPRISE_ID,
        tj.WORK_YEARS_ID,
        tj.HR_ID,
        tj.JOB_CATEGORY_ID,
        tj.JOB_TYPE_ID
        FROM
        t_job tj
        <if test="salaryId != null">
            ,t_salary ts
        </if>
        WHERE
        1 = 1
        <if test="salaryId != null">
            AND ts.SALARY_ID = #{salaryId}
            AND ts.SALARY_MAX
            &gt;=tj.SALARY_MAX
            AND ts.SALARY_MIN &lt;= tj.SALARY_MIN
        </if>
        <if test="locationId != null">
            AND
            tj.LOCATION_ID = #{locationId}
        </if>
        <if test="workYearId != null">
            AND
            tj.WORK_YEARS_ID = #{workYearId}
        </if>
        <if test="jobCategoryId != null">
            AND
            tj.JOB_CATEGORY_ID =
            #{jobCategoryId}
        </if>
        <if test="jobTypeId != null">
            AND
            tj.JOB_TYPE_ID = #{jobTypeId}
        </if>
        <if test="lastTime != null">
            AND
            tj.ADD_TIME &lt;= #{lastTime}
        </if>
        GROUP BY tj.JOB_ID
        ORDER BY tj.ADD_TIME DESC
        ) tall
        LEFT JOIN t_location
        tl ON tall.LOCATION_ID = tl.LOCATION_ID
        AND tl.LOCATION_LEVEL = 2
        AND
        tl.USE_FLAG = 1
        LEFT JOIN t_enterprise te ON tall.ENTERPRISE_ID =
        te.ENTERPRISE_ID
        AND te.USE_FLAG = 1
        LEFT JOIN t_hr th ON tall.HR_ID =
        th.HR_ID
        AND th.USE_FLAG = 1
        LEFT JOIN t_work_years twy ON
        tall.WORK_YEARS_ID = twy.WORK_YEARS_ID
        LEFT JOIN t_job_category tjc ON
        tall.JOB_CATEGORY_ID = tjc.JOB_CATEGORY_ID
        AND tjc.USE_FLAG = 1
        LEFT JOIN t_job_type tjt ON
        tall.JOB_TYPE_ID = tjt.JOB_TYPE_ID
        AND tjt.USE_FLAG = 1)
        tallTwo
        LEFT JOIN (select JOB_ID as FOCUS_JOB_ID,'1' as FOCUS_FLAG from
        t_user_job_focus where user_id = #{userId} and TYPE = '01') tujf
        ON
        tallTwo.JOB_ID = tujf.FOCUS_JOB_ID
        LIMIT #{pageIndex}
    
    </select>

如上动态SQL中有一个 where 1=1的地方,原本的情况应该写成这样

        WHERE
        <if test="salaryId != null">
            ts.SALARY_ID = #{salaryId}
            AND ts.SALARY_MAX
            &gt;=tj.SALARY_MAX
            AND ts.SALARY_MIN &lt;= tj.SALARY_MIN
        </if>

原本的情况下 当salaryId无值时,就会出现问题。改用where标签修改成如下:

        tj.JOB_CATEGORY_ID,
        tj.JOB_TYPE_ID
        FROM
        t_job tj
        <if test="salaryId != null">
            ,t_salary ts
        </if>
        <where>
        <if test="salaryId != null">
             ts.SALARY_ID = #{salaryId}
            AND ts.SALARY_MAX
            &gt;=tj.SALARY_MAX
            AND ts.SALARY_MIN &lt;= tj.SALARY_MIN
        </if>
        ......
        </where>
        GROUP BY tj.JOB_ID
        ......

说明:这种写法是 当<where>后的判断语句中有一条成立时,会在成立的语句之前加上where;如果成立的语句之前有AND或者OR,则mybatis会自动的去掉AND或OR。

五、set

主要是在update语句时使用

如下是我用代码生成器生成的一段代码如下

    <update id="updateByPrimaryKeySelective" parameterType="com.zhiji.caren.model.Job">
        update t_job
        <set>
            <if test="jobName != null">
                JOB_NAME = #{jobName,jdbcType=VARCHAR},
            </if>
            <if test="jobTypeId != null">
                JOB_TYPE_ID = #{jobTypeId,jdbcType=INTEGER},
            </if>
            <if test="jobDepartment != null">
                JOB_DEPARTMENT = #{jobDepartment,jdbcType=VARCHAR},
            </if>
            <if test="enterpriseId != null">
                ENTERPRISE_ID = #{enterpriseId,jdbcType=INTEGER},
            </if>
            <if test="jobCategoryId != null">
                JOB_CATEGORY_ID = #{jobCategoryId,jdbcType=INTEGER},
            </if>
            <if test="salaryMin != null">
                SALARY_MIN = #{salaryMin,jdbcType=INTEGER},
            </if>
            <if test="salaryMax != null">
                SALARY_MAX = #{salaryMax,jdbcType=INTEGER},
            </if>
            <if test="locationId != null">
                LOCATION_ID = #{locationId,jdbcType=INTEGER},
            </if>
            <if test="hrId != null">
                HR_ID = #{hrId,jdbcType=INTEGER},
            </if>
            <if test="workYearsId != null">
                WORK_YEARS_ID = #{workYearsId,jdbcType=INTEGER},
            </if>
            <if test="eduRequirementId != null">
                EDU_REQUIREMENT_ID =
                #{eduRequirementId,jdbcType=INTEGER},
            </if>
            <if test="jobDescription != null">
                JOB_DESCRIPTION = #{jobDescription,jdbcType=VARCHAR},
            </if>
            <if test="jobAddress != null">
                JOB_ADDRESS = #{jobAddress,jdbcType=VARCHAR},
            </if>
            <if test="auditFlag != null">
                AUDIT_FLAG = #{auditFlag,jdbcType=CHAR},
            </if>
            <if test="stikyFlag != null">
                STIKY_FLAG = #{stikyFlag,jdbcType=INTEGER},
            </if>
            <if test="negotiableFlag != null">
                NEGOTIABLE_FLAG = #{negotiableFlag,jdbcType=INTEGER},
            </if>
            <if test="hrInfoFlag != null">
                HR_INFO_FLAG = #{hrInfoFlag,jdbcType=INTEGER},
            </if>
            <if test="useFlag != null">
                USE_FLAG = #{useFlag,jdbcType=INTEGER},
            </if>
            <if test="validTime != null">
                VALID_TIME = #{validTime,jdbcType=CHAR},
            </if>
            <if test="updUserId != null">
                UPD_USER_ID = #{updUserId,jdbcType=INTEGER},
            </if>
            <if test="addTime != null">
                ADD_TIME = #{addTime,jdbcType=CHAR},
            </if>
            <if test="updTime != null">
                UPD_TIME = #{updTime,jdbcType=CHAR},
            </if>
        </set>
        where JOB_ID = #{jobId,jdbcType=INTEGER}
    </update>

看得懂纯SQL的人应该能看懂如上代码,<set>标签的作用主要是在中间那段代码的前面加上 set。如下是我没有使用<set>标签的更新语句,阅读者对比看下就能懂了。

    <update id="updateByPrimaryKey" parameterType="com.zhiji.caren.model.Job">
        update t_job
        set
        JOB_NAME = #{jobName,jdbcType=VARCHAR},
        JOB_TYPE_ID =
        #{jobTypeId,jdbcType=INTEGER},
        JOB_DEPARTMENT =
        #{jobDepartment,jdbcType=VARCHAR},
        ENTERPRISE_ID =
        #{enterpriseId,jdbcType=INTEGER},
        JOB_CATEGORY_ID =
        #{jobCategoryId,jdbcType=INTEGER},
        SALARY_MIN =
        #{salaryMin,jdbcType=INTEGER},
        SALARY_MAX =
        #{salaryMax,jdbcType=INTEGER},
        LOCATION_ID =
        #{locationId,jdbcType=INTEGER},
        HR_ID = #{hrId,jdbcType=INTEGER},
        WORK_YEARS_ID = #{workYearsId,jdbcType=INTEGER},
        EDU_REQUIREMENT_ID =
        #{eduRequirementId,jdbcType=INTEGER},
        JOB_DESCRIPTION =
        #{jobDescription,jdbcType=VARCHAR},
        JOB_ADDRESS =
        #{jobAddress,jdbcType=VARCHAR},
        AUDIT_FLAG =
        #{auditFlag,jdbcType=CHAR},
        STIKY_FLAG = #{stikyFlag,jdbcType=INTEGER},
        NEGOTIABLE_FLAG = #{negotiableFlag,jdbcType=INTEGER},
        HR_INFO_FLAG =
        #{hrInfoFlag,jdbcType=INTEGER},
        USE_FLAG = #{useFlag,jdbcType=INTEGER},
        VALID_TIME = #{validTime,jdbcType=CHAR},
        UPD_USER_ID =
        #{updUserId,jdbcType=INTEGER},
        ADD_TIME = #{addTime,jdbcType=CHAR},
        UPD_TIME = #{updTime,jdbcType=CHAR}
        where JOB_ID =
        #{jobId,jdbcType=INTEGER}
    </update>

六、foreach

我用得比较少,这里不赘述,有需要的朋友可以参考如下地址

http://haohaoxuexi.iteye.com/blog/1338557



你可能感兴趣的:(myBatis --(5)动态sql)