MyBatis學習筆記(四)動態SQL語句專題

首發於我的博客 和尚的博客
本文講解動態的SQL操作,CRUD中,CUD都需要自己手動提交事務,動態的添加語句,批量刪除的三種處理方式,提取公共的sql代碼,if標籤,where標籤,trim標籤,set標籤,choose標籤,foreach標籤,批量添加

1.trim標籤

<trim prefix="當發現有內容的時候,你在內容的最前面想加入什麼內容"           
prefixOverrides="當發現有內容的時候,你在內容的最前面想抹掉什麼內容"            
suffix="當發現有內容的時候,你在內容的最後面面想加入什麼內容"            
suffixOverrides="當發現有內容的時候,你在內容的最後面想抹掉什麼內容">        
</trim>

2.set標籤

當你發現有內容的時候,在內容的最前面加入 set 當你放下有內容的時候,檢查內容的最後面是否有逗號”,” 如果將其抹掉

3.where標籤

  • 如果發現標籤內有內容,那麼會在內容的最前面加入關鍵字 where
  • 如果有內容,會檢查內容的最前面是否含有 AND空格 或者 OR空格 ,自動將其抹掉

4.foreach標籤

  • 如果只傳了一個數組或者一個集合 collection=”array 或者 list”
  • 如果傳的是一個Map裏裝了list 就寫map的key,如果是對象裏setList,就寫對象的list屬性,這個屬性就對應一個集合
  • item相當於,他的遍歷的一個值,open=”開始加入” close=”最後加入” separator=”以什麼間隔”–>

4.choose標籤類似java中的switch

5.代碼結構

6.數據庫配置文件

同前幾天筆記

7.核心配置文件

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--加載屬性文件 -->
    <properties resource="jdbc.properties"/>
    <!--自定義設置類型的別名,也就是resultMap裏的type,避免包名已修改,在映射文件裏修改多處地方-->
    <typeAliases>
        <!-- 方式一、com.hs.model.Skill這個類設置了別名hs,之後要用這個的話,直接寫hs -->
        <!--<typeAlias type="com.hs.model.Skill" alias="hs"/> -->
        <!-- 方式二、com.hs.model這個包下的類,要用的時候直接寫類名,比如用com.hs.model.Skill,直接寫Skill -->
        <package name="com.hs.model"/>
    </typeAliases>
    <!--配置數據庫的環境-->
    <environments default="development">
        <environment id="development">
            <!--事務管理器:保證數據的完整性和一致性   關鍵信息  -->
            <!--框架:默認情況下CUD操作需要  手動提交事務
            (如同在Navicat中表中輸入了數據,沒有點那個小√,就是沒有提交事務,
            但是輸入insert語句,就自動提交事務了)  -->
            <transactionManager type="JDBC" />
            <!--使用的是連接池:百度java如何實行連接池的原理?  -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.mysql.driver}" />  <!--獲取值,${屬性文件裏的變量名},也可以直接寫值-->
                <property name="url" value="${jdbc.mysql.url}" />  <!--獲取值,${屬性文件裏的變量名},也可以直接寫值-->
                <property name="username" value="${jdbc.mysql.username}" /> <!--獲取值,${屬性文件裏的變量名},也可以直接寫值-->
                <property name="password" value="${jdbc.mysql.password}" /> <!--獲取值,${屬性文件裏的變量名},也可以直接寫值-->
            </dataSource>
        </environment>
    </environments>

    <!--加載映射文件 ,也就是含sql語句的文件-->
    <mappers>
         <!--告知映射文件方式1,一個一個的配置-->
        <mapper resource="com/hs/model/UserMapper.xml"/>
        <!-- 告知映射文件方式2,自動掃描包內的Mapper接口與配置文件 -->
        <!--<package name="com.hs.model"/>-->
    </mappers>
</configuration>

8.持久化類

User.java

package com.hs.model;

import java.util.Date;

public class User {

    /*本字段名字跟數據庫的字段一樣*/
    private Integer user_id;
    private String user_name;
    private String sex;
    private Double money;
    private Date birthday;

    public Integer getUser_id() {
        return user_id;
    }

    public void setUser_id(Integer user_id) {
        this.user_id = user_id;
    }

    public String getUser_name() {
        return user_name;
    }

    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "user_id=" + user_id +
                ", user_name='" + user_name + '\'' +
                ", sex='" + sex + '\'' +
                ", money=" + money +
                ", birthday=" + birthday +
                '}';
    }
}

9.映射文件

UserMapper.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">
<!--namespace=命名空間,唯一不重複-->
<mapper namespace="com.hs.dao.UserDao"><!--命名空間規則
傳統模式:(持久化類(實體化Bean)的類名全路徑com.hs.Skill)
接口代理模式:接口的全路徑r-->
    <!--見幫助文檔http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html-->
    <resultMap id="BaseResultMap" type="com.hs.model.User">
        <id column="user_id" property="user_id"/>
        <result column="user_name" property="user_name"/>
        <result column="sex" property="sex"/>
        <result column="money" property="money"/>
        <result column="birthday" property="birthday"/>
    </resultMap>
    <!--提取公共的SQL代碼-->
    <sql id="oa_user_columns">
        user_id,user_name,sex,money,birthday
    </sql>
    <!--別名方式的SQL代碼-->
    <sql id="oa_user_columns_alias">
        ${alias}.user_id,${alias}.user_name,${alias}.sex,${alias}.money,${alias}.birthday
    </sql>
    <!-- A.通過恆等式完成動態SQL語句 -->
    <select id="getUserListIf01" parameterType="map" resultMap="BaseResultMap">
        select
        <include refid="oa_user_columns"/>
        from
        oa_user
        where 1=1  <!-- 恆等式 ,但是影響效率-->
        <if test="name != null &amp;&amp; name != ''">
            and user_name like concat('%',#{name},'%')
        </if>
        <if test="sex != null and sex != ''">
            and sex = #{sex}
        </if>          <!-- 這個if裏沒有&&,只有&amp;&amp;或者and表示,||也只有or表示-->
    </select>
    <!-- B.通過where標籤完成動態SQL語句,沒有1=1 -->
    <select id="getUserListIf02" parameterType="map" resultMap="BaseResultMap">
        select
        <include refid="oa_user_columns"/>
        from
        oa_user
        <where>
            <if test="name != null &amp;&amp; name != ''">
                and user_name like concat('%',#{name},'%')
            </if>
            <if test="sex != null and sex != ''">
                and sex = #{sex}
            </if>          <!-- 這個if裏沒有&&,只有&amp;&amp;或者and表示,||也只有or表示-->
        </where>
    </select>
    <!-- C.trim標籤實現<trim
     prefix="當發現有內容的時候,你在內容的最前面想加入什麼內容"
     prefixOverrides="當發現有內容的時候,你在內容的最前面想抹掉什麼內容"
     suffix="當發現有內容的時候,你在內容的最後面面想加入什麼內容"
     suffixOverrides="當發現有內容的時候,你在內容的最後面想抹掉什麼內容" -->
    <select id="getUserListIf03" parameterType="map" resultMap="BaseResultMap">
        select
        <include refid="oa_user_columns"/>
        from
        oa_user
        <trim prefix="where " prefixOverrides="and || or">
            <if test="name != null &amp;&amp; name != ''">
                and user_name like concat('%',#{name},'%')
            </if>
            <if test="sex != null and sex != ''">
                and sex = #{sex}
            </if>          <!-- 見xml轉義字符 這個if裏沒有&&,只有&amp;&amp;或者and表示,||也只有or表示-->
        </trim>
    </select>

    <!--利用set標籤
    當你發現有內容的時候,在內容的最前面加入 set
    當你發現有內容的時候,檢查內容的最後面是否有逗號"," 如果有將其抹掉
    -->
    <update id="updateUser01ByPk" parameterType="com.hs.model.User">
        update oa_user
        <set>
            <if test="user_name !=null and user_name != ''">
                user_name = #{user_name},
            </if>
            <if test="sex !=null and sex != ''">
                sex = #{sex},
            </if>
            <if test="money != null"> <!--不是字符串就不要判斷是否爲空 ='' -->
                money = #{money},
            </if>
        </set>
        where user_id = #{user_id}
    </update>

    <!--利用trim標籤,,,,但是不推薦
    -->
    <update id="updateUser02ByPk" parameterType="com.hs.model.User">
        update oa_user
        <trim prefix="set" suffixOverrides=",">
            <if test="user_name !=null and user_name != ''">
                user_name = #{user_name},
            </if>
            <if test="sex !=null and sex != ''">
                sex = #{sex},
            </if>
            <if test="money != null"> <!--不是字符串就不要判斷是否爲空 ='' -->
                money = #{money},
            </if>
        </trim>
        where user_id = #{user_id}
    </update>

    <!--利用choose標籤,類似switch-->
    <select id="getSkillByChoose" parameterType="map" resultMap="BaseResultMap">
        select <include refid="oa_user_columns"/>
        from oa_user
        where
        <choose><!--注意單雙引號,when裏test='' -->
            <when test='sex!=null and sex=="男"'>
                money > 700
            </when>
            <!--<when test='sex!=null and sex=="女"'>
                money &lt;= 700   &lt;!&ndash;見xml轉義字符 小於號(因爲小於號<是標籤的開頭)的解決問題,或者這樣寫 &ndash;&gt;
            </when>-->
            <when test='sex!=null and sex="女"'>
                <![CDATA[
                money <= 700
                ]]>
            </when>     <!--裏面不能包含標籤,把<,不當做標籤的開頭 -->
            <otherwise>   <!--switch中的default-->
                1=1
            </otherwise>
        </choose>
    </select>
    <!--後面兩個屬性,前者可以不用寫,後者是使用該屬性,接收這個新添加的數據的主鍵-->
    <insert id="addSkill01" parameterType="com.hs.model.User" useGeneratedKeys="true" keyProperty="user_id">
        insert into oa_user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="user_name !=null and user_name!=''">
                user_name,
            </if>
            <if test="sex !=null and sex!=''">
                sex,
            </if>
            <if test="money !=null">
                money,
            </if>
            <if test="birthday !=null">
                birthday,
            </if>
        </trim>
        <trim prefix="values(" suffix=")" suffixOverrides=",">
            <if test="user_name !=null and user_name!=''">
                #{user_name},
            </if>
            <if test="sex !=null and sex!=''">
                #{sex},
            </if>
            <if test="money !=null">
                #{money},
            </if>
            <if test="birthday !=null">
                #{birthday},
            </if>
        </trim>
    </insert>

    <!--數組刪除,如果數組的話,請不要去設置parameterType,讓其自動識別  -->
    <delete id="deleteSkillByArray" >
        delete from oa_user where user_id in
        <!--對數組進行遍歷,
        如果只傳了一個數組或者一個集合  collection="array 或者 list
        如果傳的是一個Map裏裝了list 就寫map的key,如果是對象裏setList,就寫對象的list屬性,這個屬性就對應一個集合
        item相當於,他的遍歷的一個值,open="開始加入" close="最後加入" separator="以什麼間隔"-->
        <foreach collection="array" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>
    <!--List集合刪除 -->
    <delete id="deleteSkillByList" parameterType="list">
        delete from oa_user where user_id in
        <foreach collection="list" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>
    <delete id="deleteSkillByMap" parameterType="map">
        delete from oa_user where user_id in
        <foreach collection="id_array" item="id" open="(" close=")" separator=",">  <!-- 等於遍歷,id_array對應一個list,item就是這個list裏的值  -->
            #{id}
        </foreach>
    </delete>

    <!--批量添加-->
    <insert id="addSkillByAll" parameterType="list">
        insert into oa_user(user_name,sex,money)
        values
        <foreach collection="list" item="user" separator=",">
            (#{user.user_name},#{user.sex},#{user.money})
        </foreach>
    </insert>
</mapper>

10.封裝好的工具類

同之前的筆記

11.接口

UserDao.java

package com.hs.dao;

import com.hs.model.User;

import java.util.List;
import java.util.Map;

public interface UserDao {

    List<User> getUserListIf01(Map<String, Object> map);

    List<User> getUserListIf02(Map<String, Object> map);

    List<User> getUserListIf03(Map<String, Object> map);

    int updateUser01ByPk(User user);

    int updateUser02ByPk(User user);

    List<User> getSkillByChoose(Map<String, Object> map);

    int addSkill01(User user);

    int deleteSkillByArray(int[] array);

    int deleteSkillByList(List<Integer> list);

    int deleteSkillByMap(Map<String, Object> map);

    int addSkillByAll(List<User> list);
}

12.日誌框架配置

log4j.properties.xml

# 日誌配置文件Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
# 如果要顯示SQL語句,那麼這個位置需要配置爲命名空間log4j.logger.命名空間
log4j.logger.com.hs.dao.UserDao=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

13.測試類

MyBatisTest.java

package com.hs.test;

import com.hs.dao.UserDao;
import com.hs.model.User;
import com.hs.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 接口代理模式實現操作,在xxDao接口中,定義方法:  sql語句返回的結果類型 sql語句的id(要傳的值);
 * 不用寫實現類,直接寫測試類,具體實現見測試類
 * sql的映射文件的命名空間跟接口的全路徑一致
 * 可以根據接口的返回類型自動判斷使用selectOne還是selectList eg:返回的是一個對象的爲one,返回的是list的就是list,如果是List<Bean>,也是list
 */
public class MyBatisTest {

    /**
     * if標籤,進行兩個姓名和性別的條件查詢,通過恆等式完成動態SQL語句
     */
    @Test
    public void getUserListIf01() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("name", "悟");
            map.put("sex", "男");
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.getUserListIf01(map));
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    /**
     * if標籤,進行兩個姓名和性別的條件查詢,通過where標籤(推薦!!!):
     * 如果發現標籤內有內容,那麼會在內容的最前面加入關鍵字 where
     * 如果有內容,會檢查內容的最前面是否含有 AND空格 或者 OR空格 ,自動將其抹
     */
    @Test
    public void getUserListIf02() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("name", "悟");
            map.put("sex", "男");
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.getUserListIf02(map));
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    /**
     * if標籤,進行兩個姓名和性別的條件查詢,通過trim標籤:
     * <trim
     * prefix="當發現有內容的時候,你在內容的最前面想加入什麼內容"
     * prefixOverrides="當發現有內容的時候,你在內容的最前面想抹掉什麼內容"
     * suffix="當發現有內容的時候,你在內容的最後面面想加入什麼內容"
     * suffixOverrides="當發現有內容的時候,你在內容的最後面想抹掉什麼內容"
     * >      </trim>
     */
    @Test
    public void getUserListIf03() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("name", "悟");
            map.put("sex", "男");
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.getUserListIf03(map));
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    /**
     * 更新操作—變更數據庫
     * 利用set標籤
     * 當你發現有內容的時候,在內容的最前面加入 set
     * 當你發現有內容的時候,檢查內容的最後面是否有逗號"," 如果有將其抹掉
     */
    @Test
    public void updateUser01ByPk() throws ParseException {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            //數據
            User user = new User();
            user.setUser_id(3);
            user.setUser_name("天蓬元帥");
            //日期的轉換
            String date = "2018-8-3";
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            user.setBirthday(dateFormat.parse(date));
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.updateUser01ByPk(user));

            //重點!!!,CRUD中,除了R(查詢),不用提交事務,其餘全的自己提交事務,傳統和接口模式提交事務都是一樣的
            sqlSession.commit();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    /**
     * 更新操作—變更數據庫
     * 利用trim標籤
     *
     * @throws ParseException
     */
    @Test
    public void updateUser02ByPk() throws ParseException {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            //數據
            User user = new User();
            user.setUser_id(3);
            user.setUser_name("天蓬元帥");
            user.setMoney(1000.0);
            //日期的轉換
            String date = "2018-8-3";
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            user.setBirthday(dateFormat.parse(date));
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.updateUser02ByPk(user));
            //重點!!!,CRUD中,除了R(查詢),不用提交事務,其餘全的自己提交事務,傳統和接口模式提交事務都是一樣的
            sqlSession.commit();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    /**
     * 查詢通過choose標籤
     * 解決小於號的問題
     */
    @Test
    public void getSkillByChoose() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("sex", "女");
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.getSkillByChoose(map));
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    /**
     * 添加一個數據,然後返回這個數據自增長的主鍵信息
     */
    @Test
    public void addSkill01() throws ParseException {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            User user = new User();
            user.setUser_name("沙僧");
            user.setSex("男");
            user.setMoney(455.0);
            String date = "2018-8-5";
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            user.setBirthday(dateFormat.parse(date));
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println("影響行數"+userDao.addSkill01(user));
            sqlSession.commit();
            System.out.println("user_id:"+user.getUser_id());
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    /**
     * 傳遞傳遞數組刪除規則
     */
    @Test
    public void deleteSkillByArray(){
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.deleteSkillByArray(new int[]{6,8}));  //靜態初始化
            //事務的手動提交
            sqlSession.commit();
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    /**
     * 傳遞List集合刪除規則
     */
    @Test
    public void deleteSkillByList(){
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            List<Integer> list = new ArrayList<Integer>();
            list.add(9);
            list.add(11);
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.deleteSkillByList(list));
            //事務的手動提交
            sqlSession.commit();
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }
    /**
     * 傳遞Map裏裝list刪除規則
     */
    @Test
    public void deleteSkillByMap(){
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            List<Integer> list = new ArrayList<Integer>();
            list.add(8);
            list.add(10);
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("id_array",list);
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.deleteSkillByMap(map));
            //事務的手動提交
            sqlSession.commit();
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    /**
     * 通過list裏裝User實現批量添加
     */
    @Test
    public void addSkillByAll(){
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            List<User> list = new ArrayList<User>();
            User user1 = new User();
            user1.setUser_name("嫦娥");
            user1.setSex("女");
            user1.setMoney(1213.0);
            User user2 = new User();
            user2.setUser_name("月兔");
            user2.setSex("女");
            user2.setMoney(2113.0);
            list.add(user1);
            list.add(user2);
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            System.out.println(userDao.addSkillByAll(list));
            sqlSession.commit();
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章