MyBatis映射文件(編寫SQL語句;可有可無(無的時候,使用注解編程))


 一、映射文件

 1.簡單的增刪改(需要commit)---查

MyBatis允許增刪改直接定義以下類型返回值

  Integer、Long、Boolean、void

我們需要手動提交數據。

  sqlSessionFactory.openSession();===>需要手動提交

  sqlSessionFactory.openSession(true);===>自動提交

2.獲取insert-自增的主鍵

JDBC中Statement的方法:getGeneratedKeys();--->獲取由於執行此Statement對象而創建的所有自動生成的鍵。

    <!--自增主鍵的值
    獲取
        mysql支持自增主鍵,自增主鍵值的獲取,mybatis也是利用statement.getGeneratedKeys();
        useGeneratedKeys="true":使用自增主鍵獲取主鍵值策略
        keyProperty:指定對應的主鍵屬性,也就是mybatis獲取到主鍵值之后,將這個值封裝給JavaBean的哪個屬性
    -->
    <insert id="addEmp" parameterType="emp" useGeneratedKeys="true" keyProperty="id">
        insert into tbl_employee(last_name,email,gender)
      values(#{lastName},#{email},#{gender})
    </insert>

Oracle:自增的序列

~~ before:從序列中查主鍵的SQL在插入SQL之前執行

    <!--
        Oracle不支持自增;Oracle使用序列來模擬自增;
        每次插入的數據的主鍵是從序列中拿到的值;如何獲取到這個值
    -->
    <insert id="addEmp" databaseId="oracle" parameterType="emp">

        /*
        keyProperty:查出的主鍵值封裝給Javabean的哪個屬性
        order="BEFORE":當前SQL在插入SQL之前執行
        resultType:查出數據的返回值類型
        */
        <selectKey keyProperty="id" order="BEFORE" resultType="Integer">
            /*編寫查詢主鍵的SQL語句*/
            select 序列名.nextval from dual
        </selectKey>

       /*插入時的主鍵是從序列中拿到的*/
       insert into tbl_employee(id,last_name,email,gender)
       values (#{id},#{lastName},#{email},#{gender})
    </insert>

 

 ~~after:

    <!--
        Oracle不支持自增;Oracle使用序列來模擬自增;
        每次插入的數據的主鍵是從序列中拿到的值;如何獲取到這個值
    -->
    <insert id="addEmp" databaseId="oracle" parameterType="emp">

        /*
        keyProperty:查出的主鍵值封裝給Javabean的哪個屬性
        order="AFTER":當前SQL在插入SQL之后執行
        resultType:查出數據的返回值類型
        */
        <selectKey keyProperty="id" order="AFTER" resultType="Integer">
            /*編寫查詢主鍵的SQL語句
              獲取當前的序列值
            */
            select 序列名.currval from dual
        </selectKey>

       insert into tbl_employee(id,last_name,email,gender)
       values (序列名.nextval,#{lastName},#{email},#{gender})
    </insert>

 

 3.映射文件---參數處理(單個參數&多個參數)

單個參數:MyBatis不會做特殊處理。

  #{參數名}:取出參數值,參數名可以任意寫。

多個參數:MyBatis會做特殊處理。

  多個參數會被封裝成一份Map,

    key:param1...paramN,或者參數的索引也可以

    value:傳入的參數值

  #{ }就是從Map中獲取指定的key的值;

public Employee getEmpByIdAndLastName(Integer id,String lastName);

 

    <select id="getEmpByIdAndLastName" resultType="emp">
        select * from tbl_employee where id = #{param1} and last_name = #{param2}
    </select>

 

命名參數:明確指定封裝參數值時map的key;@Param("id")

  多個參數會被封裝成一個Map,

    key:使用@Param注解指定的值

    value:參數值

  #{指定的key}:取出對應的參數值

    public Employee getEmpByIdAndLastName(@Param("id") Integer id,@Param("lastName") String lastName);
    <select id="getEmpByIdAndLastName" resultType="emp">
        select * from tbl_employee where id = #{id} and last_name = #{lastName}
    </select>

 

 4.映射文件---參數處理---POJO&TO

POJO:

  如果多個參數正好是我們業務邏輯的數據模型,直接傳入POJO;

  #{屬性名}:取出傳入的POJO的屬性值

Map:

  如果多個參數不是業務模型中的數據,沒有對應的POJO,為了方便,我們也可以傳入Map;

  #{key}:取出map中對應的值

    public Employee getEmpByMap(Map<String,Object> map);
    <select id="getEmpByMap" resultType="emp">
        select * from tbl_employee where id=#{id} and last_name=#{lastName}
    </select>
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);

        Map<String,Object> map = new HashMap<String, Object>();
        map.put("id",2);
        map.put("lastName","jesscia");
        Employee jesscia = mapper.getEmpByMap(map);

        System.out.println(jesscia);

 

TO: 

  如果多個參數不是業務模型中的數據,但是經常要使用,推薦來編寫一個TO(Transfer Object)數據傳輸對象。 

   例如:分頁時的Page類。

 5.映射文件---參數處理---參數封裝擴展思考

    public Employee getEmp(@param("id")Integer id,String lastName);

  取值:id===>#{id/param1}  last_name===>#{param2}

public Employee getEmp((Integer id,@param("e")Employee emp);

  取值:id===>#{param1}  last_name===>#{param2.lastName/e,lastName}

 

##特別注意:如果是Collection(List、Set)類型或者是數組,也會特殊處理。也是把傳入的List或者數組封裝在map中。

  key:Collection(collection),如果是List還可以使用這個key(list)

    public Employee getEmpById(List<Integer> ids);

 

  取值:取出第一個id值: #{list[0]}

 

===============可以結合MyBatis源碼,看怎樣處理參數。=============

 

6.映射文件===參數處理===#與$取值區別

#{ }:可以獲取map中的值或者POJO對象屬性的值;

${ }:可以獲取map中的值或者POJO對象屬性的值;

select * from tbl_employee where id=${id} and last_name=#{lastName}

Preparing: select * from tbl_employee where id=2 and last_name=?

 

  區別:

      #{ }:是以預編譯的形式,將參數設置到sql語句中;PreparedStatement;防止sql注入

      ${ }:取出的值直接拼接在sql語句中,會有安全問題;

 

      大多數情況下,我們取參數的值都應該去使用#{ };

      原生JDBC不支持占位符的地方我們就可以使用${ }進行取值;

      比如分表、排序。。。:按照年份分表拆分

        select * from ${year}_salary where xxx;

        select * from tbl_employee order by ${f_name};按照什么排序

7.映射文件===參數處理===#取值時指定參數相關規則

 #{ }:更豐富的用法;

  規定參數的一些規則:

  javaType、jdbcType、mode(存儲過程)、numericScale、

  resultMap、typeHandler、jdbcTypeName、expression(未來准備支持的功能)

 

  jdbcType通常需要在某種特定的條件下被設置:

    在我們數據為null的時候,有些數據庫可能不能識別mybatis對null的處理。比如Oracle(報錯);

     JdbcType OTHER:無效的類型;因為mybatis對所有的null都映射的是原生Jdbc的OTHER類型,Oracle不能正確處理

    MyBatis里有JdbcType枚舉類,與數據庫中的各種類型進行映射。

     例如:#{email, JdbcType=NULL},在Oracle環境下,如果email為NUll,怎會出現JdbcType OTHER錯誤,把JdbcType改為NULL就行。即#{email,JdbcType=NULL}。

     

  由於全局配置中:jdbcTypeForNull=OTHER;Oracle不支持;兩種解決方法:

  1、#{email,  jdbcType=NULL};

  2、jdbcTypeForFull=NULL

    <setting  name="jdbcTypeForNull"  value="NULL"/> 在全局配置文件中設置

7.映射文件===select返回List

 

 

resultType: 如果返回是一個集合,要寫集合中元素的類型。

    public List<Employee> getEmpsByLastNameLike(String lastName);
    <select id="getEmpsByLastNameLike" resultType="emp">
        select * from tbl_employee where last_name like #{lastName}
    </select>
        List<Employee> list = mapper.getEmpsByLastNameLike("%s%");
        System.out.println("list:"+list);

8.映射文件===select記錄封裝Map

 返回一條記錄的map;key就是列名,值就是對應的值

    //返回一條記錄的map;key就是列名,值就是對應的值
    public Map<String,Object> getEmpByIdReturnMap(Integer id);
    <select id="getEmpByIdReturnMap" resultType="map">
      select * from tbl_employee where id=#{id}
    </select>
        //單條記錄的key值是列名
        Map<String, Object> map = mapper.getEmpByIdReturnMap(2);
        String lastName = (String) map.get("last_name");

 

 返回多條記錄封裝到map中:===注解@MapKey的使用:告訴MyBatis封裝的時候使用哪個屬性作為map的key

    //多條記錄封裝一個Map:Map<Integer,Employee>:鍵是這條記錄的主鍵,值是記錄封裝后的Javabean
    //告訴Mybatis封裝這個Map的時候使用哪個屬性作為map的key。
    @MapKey("id")
    public Map<Integer,Employee> getEmpByLastNameLikeReturnMap(String lastName);
    <select id="getEmpByLastNameLikeReturnMap" resultType="emp">
      select * from tbl_employee where last_name like #{lastName}
    </select>
        Map<Integer, Employee> map = mapper.getEmpByLastNameLikeReturnMap("%s%");

 

 9.映射文件===select_resultMap===自定義結果映射規則

 

 

 自動映射:

 

 

 自定義resultMap,高級映射:

    <!--自定義某個Javabean的封裝規則
        type:自定義規則的java類型
        id:唯一id,方便引用
    -->
    <resultMap id="MyEmp" type="com.atguigu.mybatis.bean.Employee">
        <!--指定主鍵列的封裝規則
            id:定義主鍵會底層有優化;
            column:指定哪一列
            property:指定對應的Javabean屬性
        -->
        <id column="id" property="id"/>
        <!--定義普通列封裝規則

        -->
        <result column="last_name" property="lastName"/>
        <!--其他不指定的列會自動封裝:我們只要寫resultMap就把全部的映射規則全寫上-->
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
    </resultMap>

    <!--resultMap:自定義結果集映射規則;-->
    <select id="getEmpById" resultMap="MyEmp">
        select * from tbl_employee where id=#{id}
    </select>

 

 10.映射文件===select_resultMap===關聯查詢_環境搭建

數據庫准備:

/*創建部門表*/
CREATE TABLE tbl_dept(
    id int(11) PRIMARY KEY auto_increment,
    dept_name VARCHAR(255)
)

/*向表Employee中插入一列*/
ALTER TABLE tbl_employee ADD COLUMN d_id INT(11);

/*添加約束,外鍵關聯*/
ALTER TABLE tbl_employee ADD CONSTRAINT fk_emp_dept
FOREIGN KEY(d_id) REFERENCES tbl_dept(id)

/*查*/
SELECT e.id id,e.last_name last_name,e.gender gender,e.email email,e.d_id d_id,
d.id did,d.dept_name dept_name
FROM tbl_employee e,tbl_dept d
WHERE e.d_id=d.id AND e.id=2

 

在Employee類中增加所屬部門(另一個類)信息。

    public Employee getEmpAndDept(Integer id);
    <!--
        場景一:
            查詢Employee的同時查詢員工對應的部門
            Employee====Department
            一個員工有與之對應的部門信息;
    -->
    <!-- 聯合查詢:級聯屬性封裝結果集 -->
    <resultMap id="MyDifEmp" type="emp">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
        <result column="email" property="email"/>
        <result column="did" property="dept.id"/>
        <result column="dept_name" property="dept.departmentName"/>
    </resultMap>
    <select id="getEmpAndDept" resultMap="MyDifEmp">
        SELECT e.id id,e.last_name last_name,e.gender gender,e.email email,e.d_id d_id,
        d.id did,d.dept_name dept_name
        FROM tbl_employee e,tbl_dept d
        WHERE e.d_id=d.id AND e.id=#{id}
    </select>
        Employee empAndDept = mapper.getEmpAndDept(2);

        System.out.println(empAndDept);
        System.out.println(empAndDept.getDept());

11.映射文件===select_resultMap關聯查詢association定義關聯對象封裝規則

    <!--使用association定義關聯的單個對象的封裝規則-->
    <resultMap id="MyDifEmp2" type="emp">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
        <result column="email" property="email"/>

        <!--association:可以指定聯合的Javabean對象
            property:指定哪個屬性是聯合的對象
            javaType:指定屬性的java類型[不能省略]
        -->
        <association property="dept" javaType="department">
            <id column="did" property="id"/>
            <result column="dept_name" property="departmentName"/>
        </association>
    </resultMap>

    <select id="getEmpAndDept" resultMap="MyDifEmp2">
        SELECT e.id id,e.last_name last_name,e.gender gender,e.email email,e.d_id d_id,
        d.id did,d.dept_name dept_name
        FROM tbl_employee e,tbl_dept d
        WHERE e.d_id=d.id AND e.id=#{id}
    </select>

 

12.映射文件===select_resultMap關聯查詢association分步查詢

    public Employee getEmpByIdStep(Integer id);
    <resultMap id="MyEmpByStep" type="emp">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
        <result column="email" property="email"/>

        <!--association:定義關聯對象的封裝規則
            select:表明當前屬性是調用select指定的方法查出的結果
            column:指定將哪一列的值傳給這個方法

            流程:使用select指定的方法(傳入column指定的這列參數的值)查出對象,並封裝給property指定的屬性
            -->
        <association property="dept"
                     select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
                     column="d_id">

        </association>
    </resultMap>
    <!--使用association進行分步查詢
        1、先按照員工id查詢員工信息
        2、根據查詢員工信息中的d_id值去部門表查詢部門信息
    -->
    <select id="getEmpByIdStep" resultMap="MyEmpByStep">
      select * from  tbl_employee where id=#{id}
    </select>
<mapper namespace="com.atguigu.mybatis.dao.DepartmentMapper">
    <select id="getDeptById" resultType="department">
        select id,dept_name departmentName from tbl_dept where id=#{id}
    </select>
</mapper>
        Employee empByIdStep = mapper.getEmpByIdStep(2);
        System.out.println(empByIdStep);
        System.out.println(empByIdStep.getDept());

 

結果:控制台上會出現兩次數據庫查詢

DEBUG 11-16 21:04:50,898 ==>  Preparing: select * from tbl_employee where id=?   (BaseJdbcLogger.java:145) 
DEBUG 11-16 21:04:50,923 ==> Parameters: 2(Integer)  (BaseJdbcLogger.java:145) 
DEBUG 11-16 21:04:50,949 ====>  Preparing: select id,dept_name departmentName from tbl_dept where id=?   (BaseJdbcLogger.java:145) 
DEBUG 11-16 21:04:50,953 ====> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
DEBUG 11-16 21:04:50,957 <====      Total: 1  (BaseJdbcLogger.java:145) 
DEBUG 11-16 21:04:50,958 <==      Total: 1  (BaseJdbcLogger.java:145) 
Employee{id=2, lastName='jesscia', email='jesscia@qq.com', gender='0', dept=Department{id=1, departmentName='開發部'}}
Department{id=1, departmentName='開發部'}

 

13.映射文件===select_resultMap關聯查詢association分步查詢&延時加載

分步查詢:1.可以組合已有的方法來完成復雜功能,2.可以使用延遲加載

 在分步查詢的基礎之上:延時加載

    <!--可以使用延遲加載
        Employee==>Dept;
            我們每次查詢Employee對象時,都將一起查詢出來。
            部門信息在我們使用的時候再去查詢。
            分步查詢的基礎之上加上兩個配置,
    -->

 

 在全局配置文件中設置:

    <settings>
        <!--顯示的指定每個我們需要更改的配置的值,即使他是默認的。防止版本更新帶來的問題-->
        <!--打開延時加載的開關-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--將積極加載改為消極加載及按需加載-->
        <setting name="aggressiveLazyLoading" value="false"/> 
    </settings>

 

 然后就可以按需加載了。

 14.映射文件===select_resultMap關聯查詢collection定義關聯集合封裝規則

場景二:查詢部門的時候將部門對應的所有員工信息也查詢出來
    public Department getDeptByIdPlus(Integer id)throws Exception;

 

 嵌套結果集的方式:

    <!--collection:嵌套結果集的方式-->
    <resultMap id="MyDept" type="department">
        <id column="did" property="id"/>
        <result column="dept_name" property="departmentName"/>

            <!--collection:定義關聯集合類型的屬性的封裝規則
                ofType:指定集合里面元素的類型
        -->
        <collection property="emps" ofType="emp">
            <id column="eid" property="id"/>
            <result column="last_name" property="lastName"/>
            <result column="email" property="email"/>
            <result column="gender" property="gender"/>
        </collection>
    </resultMap>

    <select id="getDeptByIdPlus" resultMap="MyDept">
      SELECT d.id did,d.dept_name dept_name,
        e.id eid,e.last_name last_name,e.email email,e.gender gender
      FROM tbl_dept d
      LEFT JOIN tbl_employee e
      ON d.id=e.d_id
      WHERE d.id=#{id}
    </select>

15.映射文件===select_resultMap關聯查詢collection分步查詢&延時加載

    public Department getDeptByIdStep(Integer id);
    <!--==========分步查詢===========-->
    <resultMap id="MyDept2" type="department">
        <id column="id" property="id"/>
        <result column="dept_name" property="departmentName"/>

        <collection property="emps"
                    select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDid"
                    column="id">

        </collection>
    </resultMap>
    <select id="getDeptByIdStep" resultMap="MyDept2">
        select id,dept_name departmentName from tbl_dept where id=#{id}
    </select>
    public List<Employee> getEmpsByDid(Integer did);
    <select id="getEmpsByDid" resultType="emp">
      select * from tbl_employee where d_id=#{did}
    </select>

 

 小擴展:在association和collection中的column屬性

 作用:分步查詢中的要傳遞的參數值

當多列的值傳遞過去:將多列的值封裝成map傳遞;

 column="{key1=column1, key2=column2}"

======================================

fetchType=“lazy”:表示使用延遲加載; 

  -lazy:延遲

  -eager:立即

 16.映射文件===select_resultMap的discriminator鑒別器

mybatis可以使用discriminator判斷某列的值,然后根據某列的值改變封裝行為。

封裝Employee:

  如果查詢出的是女生:就把部門信息查詢出來,否則不查詢;

  如果是男生,把last_name這一列的值賦值給email;

    <resultMap id="MyEmpDis" type="emp">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
        <result column="email" property="email"/>

        <!--column:指定判斷的列名
            javaType:列值對應的java類型
        -->
        <discriminator javaType="string" column="gender">
            <!--女生 resultType:指定封裝的結果類型-->
            <case value="0" resultType="emp">
                <association property="dept"
                             select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
                             column="d_id">
                </association>
            </case>
            <!--男生-->
            <case value="1" resultType="emp">
                <id column="id" property="id"/>
                <result column="last_name" property="lastName"/>
                <result column="gender" property="gender"/>
                <result column="last_name" property="email"/>
            </case>
        </discriminator>
    </resultMap>
    <select id="getEmpByIdStep" resultMap="MyEmpDis">
      select * from  tbl_employee where id=#{id}
    </select>

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM