1. 程式人生 > >MyBatis框架(6)動態sql

MyBatis框架(6)動態sql

什麼是動態sql:     mybatis的核心,對sql進行靈活的操作,通過對錶達式的判斷,對sql靈活的拼接

 在之前小案例的基礎上我們先進行簡單的實現一下:

 if:

 在UserMapper.xml檔案中找到:

<!-- 動態sql -->
     <!-- 綜合查詢 -->
     <select id="findBySelect" parameterType="com.MrChengs.po.UserView" resultType="com.MrChengs.po.UserCustomer" >
           select * from user
           
<where> <if test="userCustomer!=null"> <if test="userCustomer.sex!=null and userCustomer.sex!='' "> and user.sex=#{userCustomer.sex} </if> <if test="userCustomer.username!=null and userCustomer.username!=''"> and user.username like
'%${userCustomer.username}%' </if> </if> </where> </select>

 注意:where標籤可以自動去掉條件中的第一個  and

測試類: //此時值傳入username這一個值
     //動態sql
     //高階查詢
     @Test
     public void testfindBySelect() throws Exception{
           SqlSession sqlSession 
= getSqlSessionFactory().openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); UserView userView = new UserView(); UserCustomer userCustomer = new UserCustomer(); //userCustomer.setSex(1); userCustomer.setUsername("小明"); userView.setUserCustomer(userCustomer); List<User> user = mapper.findBySelect(userView); for(User u : user){ System.out.println(u); } sqlSession.close(); }

 結果:

DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]]
DEBUG [main] - ==>  Preparing: select * from user WHERE user.username like '%小明%'
DEBUG [main] - ==> Parameters:
DEBUG [main] - <==      Total: 3
User [id=16, username=張小明, birthday=null, sex=1, address=河南鄭州]
User [id=22, username=陳小明, birthday=null, sex=1, address=河南鄭州]
User [id=25, username=陳小明, birthday=null, sex=1, address=河南鄭州]
在if中判斷此時,之傳入了一個username進行查詢。

SQL片段:

把實現動態sql判斷的程式碼塊抽取出來,組成一個sql片段,在需要的時候可以直接引用,重用性高 定義一個sql片段,基於上面的程式碼進行測試和實踐: 在UserMapper.xml檔案中: 定義sql片段:
<!-- sql片段 -->
     <!-- id唯一,是sql片段的唯一標識 -->
     <!-- 基於單表定義sql片段,這樣的話sql片段的可重用性才高,在sql片段中不要包括where -->
     <sql id="selectBySql">
                <if test="userCustomer!=null">
                      <if test="userCustomer.sex!=null and userCustomer.sex!='' ">
                           and user.sex=#{userCustomer.sex}
                      </if>
                      <if test="userCustomer.username!=null and userCustomer.username!=''">
                           and user.username like '%${userCustomer.username}%'
                      </if>
                </if>
     </sql>

引用sql片段:

<!-- 動態sql -->
     <!-- 綜合查詢 -->
     <select id="findBySelect" parameterType="com.MrChengs.po.UserView" resultType="com.MrChengs.po.UserCustomer" >
           select * from user
           
           <where>
                <!-- 引用sql片段 -->
                <include refid="selectBySql"></include>
           </where>
     </select>

 測試程式碼同上次測試程式碼!

 foreach標籤:

 假設我們同時查詢多個id

select from user where id = 1 or id = 10 or id = 12 在UserMapper.xml檔案中,對之前的程式碼進行加工修改: 此時,在測試的時候,我只是測試foreach裡面的內容,所以,對程式碼進行了修改
     <!-- sql片段 -->
     <!-- id唯一,是sql片段的唯一標識 -->
     <!-- 基於單表定義sql片段,這樣的話sql片段的可重用性才高,在sql片段中不要包括where -->
     <sql id="selectBySql">
                <if test="userCustomer!=null">
                      <if test="userCustomer.sex!=null and userCustomer.sex!='' ">
                           and user.sex=#{userCustomer.sex}
                      </if>
                      <if test="userCustomer.username!=null and userCustomer.username!=''">
                           and user.username like '%${userCustomer.username}%'
                      </if>
                </if>

                <!-- foreach -->
                <!-- 測試 -->
                <!-- select from user where id = 1 or id = 10 or id = 12 -->
                
                <!-- collection:指定輸入物件的集合 -->
                <!-- item:每個遍歷生成成的物件 -->
                <!-- open:開始遍歷時 拼接的串 -->
                <!-- close:結束遍歷時 拼接的串 -->
                <!-- separator:遍歷時兩個物件中需要拼接的串 -->
                <foreach collection="ids" close=")"  item="userId" open="1=1 and (" separator="or">
                     id=#{userId}
                </foreach>
     </sql>
     
     <!-- 動態sql -->
     <!-- 綜合查詢 -->
     <select id="findBySelect" parameterType="com.MrChengs.po.UserView" resultType="com.MrChengs.po.UserCustomer" >
           select * from user
           
           <where>
                <!-- 引用sql片段 -->
                <include refid="selectBySql"></include>
           </where>
     
     </select>

 測試程式碼:

   //foreach
     //動態sql
     //高階查詢
     @Test
     public void testfindBySelect() throws Exception{
           SqlSession sqlSession = getSqlSessionFactory().openSession();
           
           UserMapper mapper = sqlSession.getMapper(UserMapper.class);
           
           UserView userView = new UserView();
           //foreach
           List<Integer> ids = new ArrayList<>();
           ids.add(1);
           ids.add(2);
           ids.add(30);
           
           userView.setIds(ids);
           
           List<User> users = mapper.findBySelect(userView);
           for(User user : users){
                System.out.println(user);
           }
           sqlSession.close();
     }

 結果:

DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]]
DEBUG [main] - ==>  Preparing: select * from user WHERE 1=1 and ( id=? or id=? or id=? )
DEBUG [main] - ==> Parameters: 1(Integer), 2(Integer), 30(Integer)
DEBUG [main] - <==      Total: 2
User [id=1, username=王五, birthday=null, sex=2, address=null]
User [id=30, username=Ma, birthday=null, sex=1, address=安徽]
對於 SELECT * FROM USER WHERE id IN(1,2,30)來說 只需要修改下面的測試程式碼,其餘的測試程式碼均不變
<foreach collection="ids" close=")"  item="userId" open="1=1 and id in(" separator=",">
               id=#{userId}
</foreach>
sql只接收一個數組引數,這時sql解析引數的名稱mybatis固定為array,如果陣列是通過一個pojo傳遞到sql則引數的名稱為pojo中的屬性名。 index:為陣列的下標。 item:為陣列每個元素的名稱,名稱隨意定義 open:迴圈開始 close:迴圈結束 separator:中間分隔輸出