MyBatis學習(四)

前言java

  最近比較鬆懈,下班回家後也懶得學習了。今晚實在是看不下去了,爭取時間學習。社會上有這麼多的資源,就看誰能搶的多吧。今天就說說MyBatis的動態SQL吧mysql

正文sql

  動態 SQL 一般要作的事情是有條件地包含 where 子句的一部分。好比:apache

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE 
  <if test="state != null">
    state = #{state}
  </if> 
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

若是這些條件沒有一個能匹配上將會怎樣?最終這條 SQL 會變成這樣:小程序

SELECT * FROM BLOG
WHERE

這會致使查詢失敗。若是僅僅第二個條件匹配又會怎樣?這條 SQL 最終會是這樣:mybatis

SELECT * FROM BLOG
WHERE 
AND title like ‘someTitle’

這個查詢也會失敗。這個問題不能簡單的用條件句式來解決,若是你也曾經被迫這樣寫過,那麼你極可能今後之後都不想再這樣去寫了。app

MyBatis 有一個簡單的處理,這在90%的狀況下都會有用。而在不能使用的地方,你能夠自定義處理方式來令其正常工做。一處簡單的修改就能獲得想要的效果:學習

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  <where> 
    <if test="state != null">
         state = #{state}
    </if> 
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

where 元素知道只有在一個以上的if條件有值的狀況下才去插入「WHERE」子句。並且,若最後的內容是「AND」或「OR」開頭的,where 元素也知道如何將他們去除。測試

好了,上面都是摘自MyBatis官網,說明了動態sql在使用中存在的問題,那我就以where爲例,跑一個小程序,仍是基於前面幾節中使用到的表。spa

<select id="getUserByObjInDynamicMethod" parameterType="org.tonny.entity.User" resultType="org.tonny.entity.User">
        SELECT * FROM users
        <where>
            <if test="id != null">
                id=#{id}
            </if>
            <if test="name != null">
                and name like #{name}
            </if>
            
        </where>
    </select>
    
    <select id="getUserByMapInDynamicMethod" parameterType="org.tonny.entity.User" resultType="org.tonny.entity.User">
        SELECT * FROM users
        <where>
            <if test="id != null">
                id=#{id}
            </if>
            <if test="name != null">
                and name like #{name}
            </if>
            
        </where>
    </select>

這部分配置與上面的同樣,使用了where標籤。對應的Java代碼以下:

@Test
    public void getUserByObjInDynamicMethod()
    {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 映射sql的標識字符串
        String sql = "org.tonny.mapper.UsersMapper.getUserByObjInDynamicMethod";
        User user = new User();
        user.setId(1);
        user.setName("%nny%");
        user.setAge(30);
        List<User> userList = sqlSession.selectList(sql, user);
        sqlSession.close();
        System.out.println(userList);
    }
    
    @Test
    public void getUserByMapInDynamicMethod()
    {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 映射sql的標識字符串
        String sql = "org.tonny.mapper.UsersMapper.getUserByObjInDynamicMethod";
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("id", 1);
        map.put("name", "%nny%");
        List<User> userList = sqlSession.selectList(sql, map);
        sqlSession.close();
        System.out.println(userList);
    }

這樣就能夠查出來了。對了,爲了能夠在控制檯查看MyBatis的SQL,須要在mybatis.xml增長配置信息:

<!-- 設置日誌打印 -->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

這樣就能夠看到輸出的sql語句了。測試結果:

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 25193812.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1806d54]
==>  Preparing: SELECT * FROM users WHERE id=? and name like ? 
==> Parameters: 1(Integer), %nny%(String)
<==    Columns: id, NAME, age
<==        Row: 1, Tonny Chien, 25
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1806d54]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1806d54]
Returned connection 25193812 to pool.
[User [id=1, name=Tonny Chien, age=25]]

還要介紹一下set標籤,它對應update中的set

<update id="updateUserByMapInDynamicMethod" parameterType="java.util.Map">
        UPDATE users
        <set>
            <if test="name != null">
                name = #{name},
            </if>
            <if test="age != null">
                age = #{age}
            </if>
        </set>
        <where>
            <if test="id != null">
                id=#{id}
            </if>
            <if test="age != null">
                <![CDATA[
                    and age > #{age}
                ]]>
            </if>
        </where>
    </update>

Java測試代碼以下:

@Test
    public void updateUserByMapInDynamicMethod()
    {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 映射sql的標識字符串
        String sql = "org.tonny.mapper.UsersMapper.updateUserByMapInDynamicMethod";
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("id", 1);
        map.put("age", 20);
        map.put("name", "北堂一刀");
        int result = sqlSession.update(sql, map);
        sqlSession.commit();
        sqlSession.close();
        System.out.println(result);
    }

執行結果:

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 30587315.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d2b9b3]
==>  Preparing: UPDATE users SET name = ?, age = ? WHERE id=? and age > ? 
==> Parameters: 北堂一刀(String), 20(Integer), 1(Integer), 20(Integer)
<==    Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d2b9b3]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d2b9b3]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d2b9b3]
Returned connection 30587315 to pool.
1

後記

就寫到這兒吧,下次再詳細些,休息了。

相關文章
相關標籤/搜索