Take you to understand MyBatis dynamic SQL

1. Introduction to Dynamic SQL

One of MyBatis's powerful features is its dynamic SQL. If you have experience using JDBC or other similar frameworks, you can experience how painful it is to stitch SQL statements according to different conditions. When splicing, make sure you ca n’t forget the necessary spaces, and also pay attention to omit the comma at the end of the column name list. The use of dynamic SQL can completely get rid of this pain. For example: before the conditional query, (some conditions may or may not involve sql judgment and sql splicing)

StringBuffer sb=new StringBuffer("SELECT * from  bills INNER JOIN  providers ON providers.providerId=bills.pid where 1=1");
if(search_title!=null&&!search_title.equals("")){
sb.append(" and title like '%"+search_title+"%'");
}
if(search_pid!=-1){ //一定选了查询条件的!
sb.append(" and pid="+search_pid);
}
if(search_pay!=-1){ //一定选了查询条件的!
sb.append(" and pay="+search_pay);
}
String sql = sb.toString();
System.out.println("SQL语句是:"+sql);

Usually using dynamic SQL cannot be an independent part. Of course MyBatis uses a powerful dynamic SQL language to improve this situation. This language can be used in any SQL mapping statement.
Dynamic SQL elements are similar to using JSTL or other similar XML-based text processors. In the previous version of MyBatis, there are many elements to understand. MyBatis 3 has greatly improved them, and now you can use less than half of the original elements. MyBatis uses powerful expressions based on OGNL (Struts2 syntax) to eliminate other elements.
The dynamic sql statement of mybatis is based on the OGNL expression. It is convenient to implement certain logic in sql statements. In general, mybatis dynamic SQL statements mainly have the following categories:

  • if statement (simple conditional judgment)
  • choose (when, otherwise) is equivalent to switch in java language, which is very similar to choose in jstl.
  • trim (prefix, suffix, etc., prefix, suffix)
  • where (mainly used to simplify the judgment of where conditions in sql statements, can handle and or intelligently, and don't have to worry about excessive results in syntax errors)
  • set (mainly used for updating)
  • foreach (especially useful when implementing mybatis in statement query)

2. Branch judgment

2.1 if element

Query data based on username and sex. If username is empty, it will only be queried based on sex; otherwise, it will only be queried based on username.
First, do not use dynamic SQL to write

<select id="selectUserByUsernameAndSex" resultType="user" parameterType="User">
		select * from user where username=#{username} and sex=#{sex}
</select>

From the above query statement, we can find that if # {username} is empty, then the query result is also empty, how to solve this problem? Use if to judge

	<select id="selectUserByUsernameAndSex" resultType="user"
		parameterType="User">
		select * from user where
		<if test="username != null">
			username=#{username}
		</if>
		<if test="sex!= null">
			and sex=#{sex}
		</if>
	</select>

We can see from this writing that if sex equals null, then the query statement is select * from user where username = # {username}, but what if usename is empty? Then the query statement is select * from user where and sex = # {sex}, this is a wrong SQL statement, how to solve it? Please see the following where statement

2.2 Dynamic SQL: if + where statement

<select id="selectUserByUsernameAndSex" resultType="User"
		parameterType="User">
		select * from user
		<where>
			<if test="username != null">
				username=#{username}
			</if>
			<if test="sex != null">
				and sex=#{sex}
			</if>
		</where>
	</select>

The "where" tag will know that if it contains a return value, it will insert a "where". In addition, if the content returned by the tag starts with AND or OR, it will be removed.

2.3 Dynamic SQL: if + set statement

Similarly, the query SQL statement above contains the where keyword. If the update keyword contains the set keyword, how do we deal with it?

<!-- 根据 id 更新 user 表的数据 -->
	<update id="updateUserById" parameterType="User">
		update user u
		<set>
			<if test="username != null and username != ''">
				u.username = #{username},
			</if>
			<if test="sex != null and sex != ''">
				u.sex = #{sex},
			</if>
		</set>
		where id=#{id}
	</update>

Write this way, if the first condition username is empty, then the sql statement is: update user u set u.sex =? Where id =?
If the first condition is not empty, then the sql statement is: update user u set u. username =?, u.sex =? where id =?
If there are extra commas, they will be removed automatically! !

2.4 Dynamic SQL: choose (when, otherwise) statement

Sometimes, we do n’t want to use all the query conditions, we just want to choose one of them, and only one of the query conditions can be satisfied. Using the choose tag can solve this kind of problem, similar to the Java switch statement.

	<select id="selectUserByChoose" resultType="User" parameterType="User">
		select * from user
		<where>
			<choose>
				<when test="id !='' and id != null">
					id=#{id}
				</when>
				<when test="username !='' and username != null">
					and username=#{username}
				</when>
				<otherwise>
					and sex=#{sex}
				</otherwise>
			</choose>
		</where>
	</select>

In other words, here we have three conditions, id, username, sex, only one can be selected as the query condition.
If id is not empty, then the query statement is: select * from user where id =?
If id is empty, then look at username Whether it is empty, if not empty, then the statement is select * from user where username = ?;
if username is empty, then the query statement is select * from user where sex =?

2.5 Dynamic SQL: understanding the trim statement

The trim mark is a formatted mark, which can complete the function of set or where mark
①. Use trim to rewrite the second point if + where statement

	<select id="selectUserByUsernameAndSex" resultType="user" parameterType="User">
		select * from user
		<trim prefix="where" prefixOverrides="and | or">
			<if test="username != null">
				and username=#{username}
			</if>
			<if test="sex != null">
				and sex=#{sex}
			</if>
		</trim>
	</select>

prefix: prefix      
prefixoverride: remove the first and or or
②, use trim to rewrite the third point if + set statement

	<!-- 根据 id 更新 user 表的数据 -->
	<update id="updateUserById" parameterType="User">
		update user u
		<trim prefix="set" suffixOverrides=",">
			<if test="username != null and username != ''">
				u.username = #{username},
			</if>
			<if test="sex != null and sex != ''">
				u.sex = #{sex},
			</if>
		</trim>
		where id=#{id}
	</update>

suffix: suffix  
suffixoverride: remove the last comma (can also be other marks, like the and in the prefix above)

2.6 Dynamic SQL: SQL fragments

Sometimes we may use a particular SQL statement very much. In order to increase the reusability of the code and simplify the code, we need to extract these codes and then directly call them when they are used.
For example: if we need to frequently perform joint queries based on user name and gender, then we will extract this code as follows:

<!--公有的代码抽象出去 -->
    <sql id="querySQL">
        <if test="username!=null and username!=''">
            and username like #{username}
        </if>
        <if test="sex!=null and sex!=''">
            and sex=#{sex}
        </if>
    </sql>

Quote sql snippet

<select id="selectUserByUsernameAndSex" resultType="user" parameterType="User">
		select * from user where 1=1
		<!--引入SQL片段-->
		<include refid="querySQL"/>
    </select>


    <select id="selectUserByUsernameAndSex1" resultType="user" parameterType="User">
        select * from user
        <!--自动的去掉多余的 And 或者 OR -->
        <where>
            <!--引入SQL片段-->
            <include refid="querySQL"/>
        </where>
    </select>

    <select id="selectUserByUsernameAndSex2" resultType="user" parameterType="User">
        select  * from  user
        <!--去掉前面多余AND或者OR-->
        <trim prefix="WHERE" prefixOverrides="AND|OR">
            <!--引入SQL片段-->
            <include refid="querySQL"/>
        </trim>
    </select>

Note:
①, it is best to define the sql fragment based on a single table to improve the reusability of the
fragment ②, do not include where in the sql fragment

2.7 Dynamic SQL: The foreach statement may be used!

https://www.cnblogs.com/hooly/p/9090167.html

[External chain image transfer failed, the source site may have an anti-theft chain mechanism, it is recommended to save the image and upload it directly (img-h2byxNqU-1586791414843) (C: \ Users \ 琳 霸 霸 \ AppData \ Roaming \ Typora \ typora-user- images \ 1583071911084.png)]

Requirement: We need to query the user
sql statements with id 1, 2, 3 in the user table : select * from user where id = 1 or id = 2 or id = 3
     select * from user where id in (1,2,3 )

  • Type of single parameter List
<select id="dynamicForeachTest" resultType="User">
		select * from user where id in
		<foreach collection="list" index="index" item="item" open="("
			separator="," close=")">
			#{item}
		</foreach>
	</select>
  • test
 public List<User> dynamicForeachTest(List<Integer> ids);
	@Test
	public void testSelectUserByListId1(){
	    List<Integer> ids = new ArrayList<Integer>();
	    ids.add(1);
	    ids.add(2);
	    ids.add(3);
	    List<User> listUser = mapper.dynamicForeachTest(ids);
	    for(User u : listUser){
	        System.out.println(u);
	    }
	}
  • Type of single parameter array array
	<select id="dynamicForeach2Test" resultType="User">
		select * from user where id in
		<foreach collection="array" index="index" item="item" open="("
			separator="," close=")">
			#{item}
		</foreach>
	</select>
public List<User> dynamicForeach2Test(Integer[] ids);
	@Test
	public void dynamicForeach2Test(){
	    Integer[] ids={1,2,3};
		List<User> listUser = mapper.dynamicForeach2Test(ids);
	    for(User u : listUser){
	        System.out.println(u);
	    }
	}
  • Encapsulate parameters into Map types
<select id="dynamicForeach3Test" resultType="User">
		select * from user where username like "%"#{username}"%" and id in
		<foreach collection="ids" index="index" item="item" open="("
			separator="," close=")">
			#{item}
		</foreach>
	</select>
public List<User> dynamicForeach3Test(Map params);
  • test
	@Test
	public void dynamicForeach3Test() {
		List ids = new ArrayList();
		ids.add(28);
		ids.add(29);
		ids.add(30);
		
		Map params = new HashMap();
		params.put("ids", ids);
		params.put("username", "张");
		
		List<User> listUser = mapper.dynamicForeach3Test(params);
		for (User u : listUser) {
			System.out.println(u);
		}
	}
Published 32 original articles · Likes 96 · Visits 1583

Guess you like

Origin blog.csdn.net/qq_44534541/article/details/105500699