1 Mybatis的動態SQL簡介 2 if標簽 3 where標簽 4 trim標簽 5 choose-when-otherwise標簽(選擇分支) 6 set標簽 7 foreach標簽 8 內置參數 9 bind標簽 10 sql標簽 ...
1 Mybatis的動態SQL簡介
- 動態SQL是Mybatis強大的特性之一,極大的簡化我們拼接SQL的操作。
- 動態SQL元素和使用JSTL或其他類似基於XML的文本處理器相似。
- Mybatis採用功能強大的OGNL表達式來簡化操作。
- if
- choose when otherwise
- trim where set
- foreach
2 if標簽
- 示例:
- EmployeeMapper.java
package com.xuweiwei.mybatis.mapper; import com.xuweiwei.mybatis.pojo.Employee; import java.util.List; public interface EmployeeMapper { public List<Employee> getEmployeeByIf(Employee employee); }
-
- EmployeeMapper.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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <select id="getEmployeeByIf" parameterType="com.xuweiwei.mybatis.pojo.Employee" resultType="com.xuweiwei.mybatis.pojo.Employee"> SELECT id,last_name,gender,email FROM employee WHERE <!-- if標簽用來判斷,和jstl中的c:if功能類似 --> <if test="id != null" > id = #{id} </if> <if test="lastName != null and lastName.trim() != ''"> and last_name like #{lastName} </if> <if test="gender != null and gender.trim() != ''"> and gender = #{gender} </if> <if test="email != null and email.trim() != ''"> and email = #{email} </if> </select> </mapper>
- 但是,一旦id為null,那麼就會報錯。
- 在where後面加1=1,然後在id前面加and id = #{id}
<?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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <select id="getEmployeeByIf" parameterType="com.xuweiwei.mybatis.pojo.Employee" resultType="com.xuweiwei.mybatis.pojo.Employee"> SELECT id,last_name,gender,email FROM employee WHERE 1=1 <!-- if標簽用來判斷,和jstl中的c:if功能類似 --> <if test="id != null" > and id = #{id} </if> <if test="lastName != null and lastName.trim() != ''"> and last_name like #{lastName} </if> <if test="gender != null and gender.trim() != ''"> and gender = #{gender} </if> <if test="email != null and email.trim() != ''"> and email = #{email} </if> </select> </mapper>
- 但是這種方法,太繁瑣了,有些人並不一定遵守啊。所以,針對這種情況,可以使用<where>標簽,它可以自動將多餘的and去掉。
3 where標簽
- 示例:
- EmployeeMapper.java
package com.xuweiwei.mybatis.mapper; import com.xuweiwei.mybatis.pojo.Employee; import java.util.List; public interface EmployeeMapper { public List<Employee> getEmployeeByIf(Employee employee); }
-
- EmployeeMapper.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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <select id="getEmployeeByIf" parameterType="com.xuweiwei.mybatis.pojo.Employee" resultType="com.xuweiwei.mybatis.pojo.Employee"> SELECT id,last_name,gender,email FROM employee <!-- where 標簽 可以將多餘的and去掉 --> <where> <!-- if標簽用來判斷,和jstl中的c:if功能類似 --> <if test="id != null" > id = #{id} </if> <if test="lastName != null and lastName.trim() != ''"> and last_name like #{lastName} </if> <if test="gender != null and gender.trim() != ''"> and gender = #{gender} </if> <if test="email != null and email.trim() != ''"> and email = #{email} </if> </where> </select> </mapper>
-
- 測試
package com.xuweiwei.mybatis.test; import com.xuweiwei.mybatis.mapper.EmployeeMapper; import com.xuweiwei.mybatis.pojo.Employee; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MybatisTest { /** * 查詢 * * @throws IOException */ @Test public void test() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try { EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class); Employee emp = new Employee(); emp.setId(3); emp.setEmail("[email protected]"); List<Employee> employees = employeeMapper.getEmployeeByIf(emp); System.out.println(employees); } finally { session.close(); } } }
- 但是,這樣也有問題,有人喜歡將and放在每個條件的最後,請看下麵的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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <select id="getEmployeeByIf" parameterType="com.xuweiwei.mybatis.pojo.Employee" resultType="com.xuweiwei.mybatis.pojo.Employee"> SELECT id,last_name,gender,email FROM employee <!-- where 標簽 可以將多餘的and去掉 --> <where> <!-- if標簽用來判斷,和jstl中的c:if功能類似 --> <if test="id != null" > id = #{id} and </if> <if test="lastName != null and lastName.trim() != ''"> last_name like #{lastName} and </if> <if test="gender != null and gender.trim() != ''"> gender = #{gender} and </if> <if test="email != null and email.trim() != ''"> email = #{email} and </if> </where> </select> </mapper>
- 此時,Mybatis內心是崩潰的,你們這些愚蠢的人類,就是瞎折騰。那麼此時可以使用trim標簽。
4 trim標簽
- 示例:
- EmployeeMapper.java
package com.xuweiwei.mybatis.mapper; import com.xuweiwei.mybatis.pojo.Employee; import java.util.List; public interface EmployeeMapper { public List<Employee> getEmployeeByIf(Employee employee); }
-
- EmployeeMapper.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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <select id="getEmployeeByIf" parameterType="com.xuweiwei.mybatis.pojo.Employee" resultType="com.xuweiwei.mybatis.pojo.Employee"> SELECT id,last_name,gender,email FROM employee <!-- trim標簽 prefix:在trim標簽範圍內的所有語句,前面加上prefix屬性對應的值 prefixOverrides:將在trim標簽範圍內的所有語句前面多餘的和prefixOverrides相等的值去掉 suffix:和prefix相反 suffixOverrides:和prefixOverrides相反 --> <trim prefix="where" suffixOverrides="and"> <!-- if標簽用來判斷,和jstl中的c:if功能類似 --> <if test="id != null"> id = #{id} and </if> <if test="lastName != null and lastName.trim() != ''"> last_name like #{lastName} and </if> <if test="gender != null and gender.trim() != ''"> gender = #{gender} and </if> <if test="email != null and email.trim() != ''"> email = #{email} and </if> </trim> </select> </mapper>
-
- 測試
package com.xuweiwei.mybatis.test; import com.xuweiwei.mybatis.mapper.EmployeeMapper; import com.xuweiwei.mybatis.pojo.Employee; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MybatisTest { /** * 查詢 * * @throws IOException */ @Test public void test() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try { EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class); Employee emp = new Employee(); emp.setId(3); emp.setEmail("[email protected]"); List<Employee> employees = employeeMapper.getEmployeeByIf(emp); System.out.println(employees); } finally { session.close(); } } }
- 當然,針對2if標簽所面對的問題,也可以使用trim來解決,請看如下的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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <select id="getEmployeeByIf" parameterType="com.xuweiwei.mybatis.pojo.Employee" resultType="com.xuweiwei.mybatis.pojo.Employee"> SELECT id,last_name,gender,email FROM employee <!-- trim標簽 prefix:在trim標簽範圍內的所有語句,前面加上prefix屬性對應的值 prefixOverrides:將在trim標簽範圍內的所有語句前面多餘的和prefixOverrides相等的值去掉 suffix:和prefix相反 suffixOverrides:和prefixOverrides相反 --> <trim prefix="where" prefixOverrides="and"> <!-- if標簽用來判斷,和jstl中的c:if功能類似 --> <if test="id != null"> id = #{id} </if> <if test="lastName != null and lastName.trim() != ''"> and last_name like #{lastName} </if> <if test="gender != null and gender.trim() != ''"> and gender = #{gender} </if> <if test="email != null and email.trim() != ''"> and email = #{email} </if> </trim> </select> </mapper>
5 choose-when-otherwise標簽(選擇分支)
- 示例:查詢雇員信息,如果id不是null,就用id查詢,以此類推。
- EmployeeMapper.java
package com.xuweiwei.mybatis.mapper; import com.xuweiwei.mybatis.pojo.Employee; import java.util.List; public interface EmployeeMapper { public List<Employee> getEmployeeByIf(Employee employee); }
-
- EmployeeMapper.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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <select id="getEmployeeByIf" parameterType="com.xuweiwei.mybatis.pojo.Employee" resultType="com.xuweiwei.mybatis.pojo.Employee"> SELECT id,last_name,gender,email FROM employee <where> <choose> <when test="id != null"> id = #{id} </when> <when test="lastName != null"> last_name like #{lastName} </when> <when test="gender != null"> gender = #{gender} </when> <otherwise> email = #{email} </otherwise> </choose> </where> </select> </mapper>
6 set標簽
- 示例:根據指定的條件根據雇員信息
- EmployeeMapper.java
package com.xuweiwei.mybatis.mapper; import com.xuweiwei.mybatis.pojo.Employee; public interface EmployeeMapper { public boolean updateEmployee(Employee employee); }
-
- EmployeeMapper.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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <update id="updateEmployee" parameterType="com.xuweiwei.mybatis.pojo.Employee"> UPDATE employee SET <if test="lastName != null"> last_name = #{lastName}, </if> <if test="gender != null"> gender = #{gender}, </if> <if test="email != null"> email = #{email} </if> <where> id = #{id} </where> </update> </mapper>
-
- 測試
package com.xuweiwei.mybatis.test; import com.xuweiwei.mybatis.mapper.EmployeeMapper; import com.xuweiwei.mybatis.pojo.Employee; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; public class MybatisTest { /** * 查詢 * * @throws IOException */ @Test public void test() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try { EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class); Employee emp = new Employee(); emp.setGender("男"); emp.setId(3); emp.setEmail("[email protected]"); emp.setLastName("許飛"); boolean flag = employeeMapper.updateEmployee(emp); System.out.println(flag); } finally { session.close(); } } }
- 這樣,看似沒有問題,如果一旦email為null的話,那麼資料庫就會發出錯誤
- 測試代碼如下
package com.xuweiwei.mybatis.test; import com.xuweiwei.mybatis.mapper.EmployeeMapper; import com.xuweiwei.mybatis.pojo.Employee; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; public class MybatisTest { /** * 查詢 * * @throws IOException */ @Test public void test() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try { EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class); Employee emp = new Employee(); emp.setGender("男"); emp.setId(3); emp.setLastName("許飛"); boolean flag = employeeMapper.updateEmployee(emp); System.out.println(flag); } finally { session.close(); } } }
- 所以,使用SET標簽,這樣Mybatis就會將多餘的逗號(,)幹掉
<?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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <update id="updateEmployee" parameterType="com.xuweiwei.mybatis.pojo.Employee"> UPDATE employee <set> <if test="lastName != null"> last_name = #{lastName}, </if> <if test="gender != null"> gender = #{gender}, </if> <if test="email != null"> email = #{email} </if> </set> <where> id = #{id} </where> </update> </mapper>
- 當然,你也可以使用trim標簽哦。
7 foreach標簽
- 示例:根據主鍵批量查詢雇員信息
- SQL語句如下:
SELECT `id`,`last_name`,`gender`,`email`,`department_id` FROM `employee` WHERE id IN (3,4,5);
-
- EmployeeMapper.java
package com.xuweiwei.mybatis.mapper; import com.xuweiwei.mybatis.pojo.Employee; import org.apache.ibatis.annotations.Param; import java.util.List; public interface EmployeeMapper { public List<Employee> findEmployeesByIds(@Param("ids") Integer[] ids); }
-
- EmployeeMapper.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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <select id="findEmployeesByIds" resultType="com.xuweiwei.mybatis.pojo.Employee"> SELECT `id`,`last_name`,`gender`,`email`,`department_id` FROM `employee` <!-- foreach標簽,遍歷集合 collection:需要遍歷的集合 item:將遍歷的每個元素設置到item中 separator:每個元素之間的分割符 open:將遍歷的結果拼湊一個開始的字元 close:將遍歷的結果拼接一個結束的字元 --> <foreach collection="ids" item="id" open="where id in ( " close=")" separator=","> #{id} </foreach> </select> </mapper>
-
- 測試
package com.xuweiwei.mybatis.test; import com.xuweiwei.mybatis.mapper.EmployeeMapper; import com.xuweiwei.mybatis.pojo.Employee; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MybatisTest { /** * 查詢 * * @throws IOException */ @Test public void test() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try { EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class); Integer[] ids = new Integer[3]; ids[0] = 3; ids[1] = 4; ids[2] = 5; List<Employee> employees = employeeMapper.findEmployeesByIds(ids); System.out.println(employees); } finally { session.close(); } } }
- 以MySQL為例,foreach的第二種場景,就是批量插入,示例代碼如下
- EmployeeMapper.java
package com.xuweiwei.mybatis.mapper; import com.xuweiwei.mybatis.pojo.Employee; import org.apache.ibatis.annotations.Param; import java.util.List; public interface EmployeeMapper { public boolean insertEmployees(@Param("emps") List<Employee> emps); }
-
- EmployeeMapper.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="com.xuweiwei.mybatis.mapper.EmployeeMapper"> <insert id="insertEmployees"> INSERT INTO `employee` (`last_name`,`gender`,`email`) VALUES <foreach collection="emps" item="emp" separator=","> (#{emp.lastName},#{emp.gender},#{emp.email}) </foreach> </insert> </mapper>
-
- 測試
package com.xuweiwei.mybatis.test; import com.xuweiwei.mybatis.mapper.EmployeeMapper;