動態sql是myBatis中至關有用的一個知識點,整體來講,動態sql有以下幾類:sql
1>if語句(簡單的條件判斷)
mybatis
2>choose(至關於case when),即C語言中的switth
oracle
3>trim(對包含的內容加上prefix(前綴)、或者suffix(後綴)等)
ide
4>where(簡化SQL語句中where條件判斷)
ui
5>set(用於 更新時設置)
code
6>foreach(實現myBatis in語句查詢時有用)
xml
以下例子均是普通sql操做的例子,若是採用oracle中的存儲過程時,請直接看後面講解。
blog
1、if語句
ip
使用環境舉例:查詢招聘列表,根據地點、薪資、工做經驗等篩選條件進行篩選。rem
分析:這個時候,條件是動態的,能夠所有選擇,也能夠只選擇一部分。
動態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 <= #{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查詢條件才帶上這個篩選條件;不然,不帶上這個篩選條件(即沒有選擇這個篩選條件)。
2、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 <= #{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語句完成 篩選條件 多選一的時候。即篩選條件始終是隻能選擇一個或者不選。
3、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 (,後面用 ")"代替","。
4、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 >=tj.SALARY_MAX AND ts.SALARY_MIN <= 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 <= #{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 >=tj.SALARY_MAX AND ts.SALARY_MIN <= 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 >=tj.SALARY_MAX AND ts.SALARY_MIN <= tj.SALARY_MIN </if> ...... </where> GROUP BY tj.JOB_ID ......
說明:這種寫法是 當<where>後的判斷語句中有一條成立時,會在成立的語句以前加上where;若是成立的語句以前有AND或者OR,則mybatis會自動的去掉AND或OR。
5、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>
6、foreach
我用得比較少,這裏不贅述,有須要的朋友能夠參考以下地址