1. 程式人生 > >mybatis的動態sql與核心對映

mybatis的動態sql與核心對映

一:mybatis中如何使用動態sql:
MyBatis的強大特性之一便是它的動態 SQL。如果你有使用 JDBC 或其他類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句有多麼痛苦。拼接的時候要確保不能忘了必要的空格,還要注意省掉列名列表最後的逗號。有些時候,SQL語句where條件中,需要一些安全判斷,例如按某一條件查詢時如果傳入的引數是空,此時查詢出的結果很可能是空的,也許我們需要引數為空時,是查出全部的資訊。使用Oracle的序列、mySQL的函式生成Id。這時我們可以使用動態SQL。利用動態 SQL 這一特性可以徹底擺脫這種痛苦。通常使用動態 SQL 不可能是獨立的一部分,MyBatis 當然使用一種強大的動態 SQL 語言來改進這種情形,這種語言可以被用在任意的 SQL 對映語句中。動態 SQL 元素和使用 JSTL 或其他類似基於 XML 的文字處理器相似。MyBatis 採用功能強大的基於 OGNL 的表示式來消除其他元素。

MyBatis中用於實現動態SQL的元素主要有:
1、if和where
if就是簡單的條件判斷,利用if語句我們可以實現某些簡單的條件選擇。動態 SQL 通常要做的事情是有條件地包含 where 子句的一部分。
where元素的作用是會在寫入where元素的地方輸出一個where,另外一個好處是你不需要考慮where元素裡面的條件輸出是什麼樣子的,MyBatis會智慧的幫你處理。如果所有的條件都不滿足那麼MyBatis就會查出所有的記錄;如果輸出後是and這個單詞開頭的,MyBatis會把第一個單詞and忽略,當然如果是or開頭的,MyBatis也會把它忽略。此外,在where元素中你不需要考慮空格的問題,MyBatis會智慧的幫你加上。

2、choose(when,otherwise)
choose元素的作用就相當於JAVA中的switch語句,基本上跟JSTL中的choose的作用和用法是一樣的,通常都是與when和otherwise搭配的。
3、trim

trim元素的主要功能是可以在自己包含的內容前加上某些字首,也可以在其後加上某些字尾,與之對應的屬性是prefix和suffix;可以把包含內容的首部某些內容覆蓋,即忽略,也可以把尾部的某些內容覆蓋,對應的屬性是prefixOverrides和suffixOverrides;正因為trim有這樣的功能,所以我們也可以非常簡單的利用trim來代替where元素的功能
4、set
set元素主要是用在更新操作的時候,它的主要功能和where元素其實是差不多的,主要是在set標籤包含的語句前輸出一個set。如果包含的語句是以逗號結束的話將會把該逗號忽略。如果set包含的內容為空的話則會出錯。有了set元素我們就可以動態的更新那些修改了的欄位,而不用每次更新全部欄位。

5、foreach
foreach的主要用在構建in條件中,它可以在SQL語句中迭代一個集合。foreach元素的屬性主要有item,index,collection,open,separator,close。
item表示集合中每一個元素進行迭代時的別名,index指定一個名字,用於表示在迭代過程中,每次迭代到的位置,open表示該語句以什麼開始,separator表示在每次進行迭代之間以什麼符號作為分隔符,close表示以什麼結束。
collection屬性用於指定傳入引數的型別。該屬性是必須指定的,在不同情況下,該屬性的值是不一樣的,主要有一下3種情況:
如果傳入的是單引數且引數型別是一個List型別的時候,collection屬性值為list。
如果傳入的是單引數且引數型別是一個array陣列的時候,collection的屬性值為array。
如果傳入的引數是多個的時候,我們就需要把它們封裝成一個Map了,當然單引數也可以封裝成map。實際上在傳入引數的時候,MyBatis也是把它封裝成一個Map的,List例項將會以“list”作為鍵,而陣列例項將會以“array”作為鍵。這個時候collection屬性值就是傳入的List或array物件在封裝自身的map裡面中的對應key。

具體使用
1.通過resource載入單個的對映檔案UserMapper.xml

通過mapper介面載入單個mapper,要遵循一定的規範:
(1)前提是使用mapper代理開發(已經有4個規範)
(2)需要將mapper介面類名和mapper.xml對映檔名稱保持一致,且在同一目錄下
在這裡插入圖片描述

通過批量載入mapper(推薦使用):實現條件是
要滿足mapper介面載入對映檔案和使用mapper代理開發同時滿足
在這裡插入圖片描述

mybatis的核心輸入對映和輸出對映開始:
輸入對映:
通過parameterType指定輸入引數型別,型別可以是簡單型別、hashmap、pojo的包裝型別

輸出對映
1,resultType
使用resultType進行輸出對映時,只有查詢輸出結果列名和pojo中的屬性名一致才可以,對映成功
如果查詢出來的列名和pojo中的屬性名沒有一個一致的,就不會建立pojo物件
如果查詢出來的列名和pojo中的屬性名有一個一致,就會建立pojo物件
輸出pojo物件和pojo列表
不管是輸出的pojo單個物件還是一個列表(list中包含pojo),在mapper.xml中resultType指定的型別是一樣的
在mapper.java指定的方法返回值型別不一樣:
(1)輸出單個pojo物件,方法返回值是個單個物件型別
(2)輸出pojo物件list,方法返回值就是list物件型別
在動態代理物件中,是根據mapper方法的返回值型別來確定是呼叫selectOne(返回單個物件)還是selectList(返回集合物件)
2,resultMap
使用resultMap進行對映時,查詢結果列名和pojo的屬性名不一致時,resultMap會對列名和pojo屬性名進行對映,保證其成功對映

1—建立 User 類
package com.offcn.entity;
import java.util.Date;
import java.util.List;
public class User {

private List<Address> addressList;
public Role getRole() {
    return role;
}

private Role role;

public List<Address> getAddressList() {
    return addressList;
}

public void setAddressList(List<Address> addressList) {
    this.addressList = addressList;
}}

2.第二部—定義介面UserMapper
package com.offcn.dao;

import com.offcn.entity.User;
import org.apache.ibatis.annotations.Param;

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

public interface UserMapper {
List selectByName(User user);

/*     使用註解方式注入引數*/
/*List<User> selectByName(@Param("userName")
                                String userName, @Param("userRole") Integer userRole);*/

/*------*/
List<User> selectByMap(Map<String,String> map);


/*-------*/
List<User> selectByRole(User u);

/*-------*/
List<User> selectAddressByUserName(String userName);
/*---增加一個使用者--*/
int addUser(User user);

/*---修改一個使用者*/
int updateUser(User user);

/*-----查詢userRole的2或3的所有使用者,傳一個數組引數*/

List<User> selectArrayUser(Integer[] userRole);

List<User> selectArrayUser(List<Integer> userRole);

}

3.第三步
對映檔案UserMapper.xml配置 :

<mapper namespace="com.offcn.dao.UserMapper">
<!--這個id的名字必須與你的dao層方法名一樣-->
<!--prefix加字首,prefixOverrides去除第一個and關鍵詞,suffix加字尾,suffixOverrides去除最後一個符號或關鍵字-->
<select id="selectByName"  resultType="User">
    select u.*,r.roleName from smbms_user u,smbms_role r
    <trim prefix="where" prefixOverrides="and" suffix="and u.userRole=r.id">
     <if test="userRole!=null">
         and userRole=#{userRole}
     </if>
    <if test="userName!=null and userName!=''">
       and userName  like concat ('%',#{userName},'%')
    </if>
    </trim>

</select>

<insert id="addUser" parameterType="User" >

    insert into smbms_user(userName,userPassword,UserCode,gender,birthday)
    values (#{userName},#{userPassword},#{userCode},#{gender},#{birthday})


  /*插入*/
</insert>
<!--prefix 加上字首 -->
<update id="updateUser" parameterType="User">
    update smbms_user

    <trim prefix="set" suffixOverrides="," suffix="where id=#{id}">
        <if test="userCode !=null">userCode=#{userCode},</if>
        <if test="userName !=null">userName=#{userName},</if>
        <if test="userPassword  !=null">userPassword=#{userPassword},</if>
        <if test="gender !=null">gender=#{gender},</if>
        <if test="birthday !=null">birthday=#{birthday},</if>

    </trim>

</update>

<!--<select id="selectByMap" parameterType="Map" resultType="User">
     select u.*,r.roleName from smbms_user u,smbms_role r
    where userName like concat ('%',#{uName},'%') and
    userRole =#{uRole} and u.userRole=r.id
</select>-->

<!--resultMap的id與你select的resultMap的值對應-->
<!--type是代表你的返回值型別(可以給別名)-->
<resultMap id="selectByMapResult" type="User">
    <!--property的id代表 標籤實體類的屬性名,column代表是你的資料庫列名-->
    <!--兩種id必須相匹配,不匹配的時候兩種情況-->
    <!--兩種情況:-->
    <!--第一種:是你的標籤實體類的屬性名與你的資料庫列名相對應-->
    <!--第二種:複雜查詢的時候(一對一,一對多)-->
    <id property="id" column="id"></id>
    <result property="userName" column="userName"></result>
    <result property="userRole" column="userRole"></result>
    <result property="userPassword" column="userPassword"></result>


</resultMap>

<select id="selectByMap" parameterType="Map" resultMap="selectByMapResult">
     select u.*,r.id from smbms_user u,smbms_role r
    where userName like concat ('%',#{uName},'%') and
    userRole =#{uRole} and u.userRole=r.id
</select>

 <!--resultMap的id與下面的<select>標籤的resultMap的值一樣-->
<resultMap id="selectRoleMap" type="User">
    <id property="id" column="id"></id>
    <result property="userName" column="userName"></result>
    <result property="userRole" column="userRole"></result>
    <!--配置一對一的關係,association拿到的是你的屬性名-->
    <!--javaType代表你的返回型別-->
    <association property="role" javaType="Role">
        <id property="id" column="r_id"></id>
        <result property="roleName" column="roleName"></result>
        <result property="roleCode" column="roleCode"></result>
         <!--如果下面select標籤裡的查詢語句u的id與r的id欄位名一致時,需要給r的id取一個別名r_id-->
    </association>
</resultMap>

<!--resultMap的值自己定義-->
<select id="selectByRole" parameterType="User" resultMap="selectRoleMap">

     select u.*,r.id as r_id,r.roleName,r.roleCode  from smbms_user u,smbms_role r
    where userName like concat ('%',#{userName},'%') and
    userRole =#{userRole} and u.userRole=r.id

</select>


<!--根據名字查詢地址一對多的關係-->
<resultMap id="selectAddressMap" type="User">
    <id property="id" column="id"></id>
    <result property="userName" column="userName"></result>
    <!--開始配置一對多的關係-->
    <collection property="addressList" ofType="Address">
        <!--<id property="id" column="id"></id>-->
        <result property="addressDesc" column="addressDesc"></result>
        <result property="contact" column="contact"></result>
    </collection>

</resultMap>

<select id="selectAddressByUserName" parameterType="String" resultMap="selectAddressMap">
      select u.*,a.addressDesc,a.contact from smbms_address a,smbms_user u
       where a.userId=u.id and u.userName=#{userName}
</select>

<!--collection你要遍歷的型別  list是指List集合 array是指陣列 item你要自定義的條目名-->
<!--open以什麼開始    separator以什麼分割 close以什麼結束 -->
<!--#{uRole}的值與item的名字要一樣-->
<select id="selectArrayUser"  resultType="User">
    select * from smbms_user where userRole in
    <foreach collection="list" item="uRole" open="(" separator="," close=")">
      #{uRole}
    </foreach>
</select>

第四部:
測試類:

/----動態sql–/

        /*-查詢全部-*/

        /*SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
        AddressMapper mapper = sqlSession.getMapper(AddressMapper.class);
        List<Address> addresses = mapper.selectAllAddress();
        for (Address a :addresses
                ) {
            System.out.println(a.getAddressDesc()+"--"+a.getContact());
        }*/

        /*----模糊c查詢----*/
        /*SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
        AddressMapper mapper = sqlSession.getMapper(AddressMapper.class);
        Address address = mapper.selectOneAddress("李");
        System.out.println(address.getContact()+"---");*/

        /*--查詢一條--*/
       /* SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
        AddressMapper mapper = sqlSession.getMapper(AddressMapper.class);
        Address address = mapper.checkAddress(3);
        System.out.println(address);*/

        /*-----註解配置的對映------*/
        /*查詢mysql表中所有Address的方法*/
        /*SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
        AddressMapper mapper = sqlSession.getMapper(AddressMapper.class);
        List<Address> list = mapper.selectAllAddress();
        for (Address aa:list) {
            System.out.println(aa.getContact()+"###");
        }*/

        /*----------通過管理員名字模糊查詢所有使用者---------*/
       /* SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user=new User();
        user.setUserRole(3);
        user.setUserName("孫");
        List<User> list=mapper.selectByName(user);
        for (User u:list
             ) {
            System.out.println(u.getUserName()+"000");
        }*/

        SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        /*User user=new User();
        user.setUserRole(3);
        user.setUserName("孫");*/
       /* Map<String,String> map=new HashMap<String,String>();
        map.put("uName","孫");
        map.put("uRole","3");*/
        /*--如果你使用Map集合來進行傳參,鍵名必須與你UserMapper.xml檔案裡面的佔位符#{}的值必須一致--*/
       /* List<User> list=mapper.selectByRole(user);
        for (User u:list) {

            System.out.println(u.getUserName()+"---"+u.getUserRole());
            Role role = u.getRole();
            System.out.println(role.getRoleName()+"--"+role.getRoleCode());



        }*/

       /*---一對多:查詢某一個人的所有地址---*/
       /* List<User> list = mapper.selectAddressByUserName("張華");
        for (User u:list
             ) {

            System.out.println(u.getUserName()+"\t");
            List<Address> addressList=u.getAddressList();
            for (Address a:addressList
                 ) {
                System.out.println(a.getContact()+"--"+a.getAddressDesc());
            }

        }*/

       /* List<User> list = mapper.selectByName("張", null);
        for (User u:list
             ) {
            System.out.println(u.getUserName()+"--"+u.getUserRole());
        }*/

       /*--增加一個--*/
        /*User user=new User();
        user.setUserName("vvv");
        user.setBirthday(new Date());
        user.setUserCode("asd");
        user.setUserPassword("2222");
        user.setGender(2);
        int i = mapper.addUser(user);
        System.out.println(i);*/

        /*---修改一個---*/
       /* User user=new User();
        user.setUserName("尼瑪");
        user.setGender(2);
        user.setId(2);
        int i = mapper.updateUser(user);
        System.out.println(i);*/

        /*User user=new User();
        user.setUserName("尼瑪");

        List<User> list = mapper.selectByName(user);
        for (User u:list
             ) {
            System.out.println(u.getUserName());
        }*/
        List<Integer> list1=new ArrayList<Integer>();
        list1.add(2);
        list1.add(3);
        List<User> list = mapper.selectArrayUser(list1);
        for (User u:list
             ) {
            System.out.println(u.getUserName());
        }