MyBatis基礎入門


1.MyBatis概述

  • MyBatis是一個優秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如注冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。
  • Mybatis通過xml或注解的方式將要執行的各種statement(statement、preparedStatement、CallableStatement)配置起來,並通過java對象和statement中的sql進行映射生成最終執行的sql語句,最后由mybatis框架執行sql並將結果映射成java對象並返回。

2.為什么要使用MyBatis(使用JDBC編程有哪些問題)?

  1. 數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用數據庫鏈接池可解決此問題。

  2. Sql語句在代碼中硬編碼,造成代碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java代碼。

  3. 使用preparedStatement向占有位符號傳參數存在硬編碼,因為sql語句的where條件不一定,可能多也可能少,修改sql還要修改代碼,系統不易維護。
  4. 對結果集解析存在硬編碼(查詢列名),sql變化導致解析代碼變化,系統不易維護,如果能將數據庫記錄封裝成pojo對象解析比較方便。

3.MyBatis架構

  1. MyBatis配置
    • SqlMapConfig.xml,此文件作為mybatis的全局配置文件,配置了mybatis的運行環境等信息

    • mapper.xml文件即sql映射文件,文件中配置了操作數據庫的sql語句。此文件需要在SqlMapConfig.xml中加載
  2. 通過mybatis環境等配置信息構造SqlSessionFactory即會話工廠

  3. 由會話工廠創建sqlSession即會話,操作數據庫需要通過sqlSession進行

  4. mybatis底層自定義了Executor執行器接口操作數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器。
  5. Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sql的id即是Mapped statement的id。

  6. Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數。

  7. Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor

4.MyBatis入門

創建Maven工程

修改pom.xml導入MyBatis以及Junit和MySql驅動的jar包

<dependencies>
        <!-- MySQL驅動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.29</version>
        </dependency>

        <!--junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- mybatis -->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
</dependencies>

classpath目錄下創建MyBatis的核心配置文件SqlMapConfig.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>
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事務管理 -->
            <transactionManager type="JDBC" />
            <!-- 數據庫連接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url"
                    value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>

    <!-- 加載映射文件 -->
    <mappers>
        <mapper resource="User.xml" />
    </mappers>

</configuration>

 

創建測試數據庫

 

創建po類  ---Po類作為mybatis進行sql映射使用,po類通常與數據庫表對應

package pojo;

import java.util.Date;

public class User {

    private int id;
    private String username;// 用戶姓名
    private String sex;// 性別
    private Date birthday;// 生日
    private String address;// 地址

getter and setter方法......

    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
                + address + "]";
    }      

}

創建sql映射文件User.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:命名空間,做sql隔離 -->
<mapper namespace="test">

    <!-- 
    id:sql語句唯一標識
    parameterType:指定傳入參數類型
    resultType:返回結果集類型
    #{}占位符:起到占位作用,如果傳入的是基本類型(string,long,double,int,boolean,float等),那么#{}中的變量名稱可以隨意寫.
     -->
    <select id="findUserById" parameterType="java.lang.Integer" resultType="cn.itheima.pojo.User">
        select * from user where id=#{id}
    </select>
    
    <!-- 
    如果返回結果為集合,可以調用selectList方法,這個方法返回的結果就是一個集合,所以映射文件中應該配置成集合泛型的類型
    ${}拼接符:字符串原樣拼接,如果傳入的參數是基本類型(string,long,double,int,boolean,float等),那么${}中的變量名稱必須是value
    注意:拼接符有sql注入的風險,所以慎重使用
     -->
    <select id="findUserByUserName" parameterType="java.lang.String" resultType="cn.itheima.pojo.User">
        select * from user where username like '%${value}%'
    </select>
    
    <!-- 
    #{}:如果傳入的是pojo類型,那么#{}中的變量名稱必須是pojo中對應的屬性.屬性.屬性.....
    如果要返回數據庫自增主鍵:可以使用select LAST_INSERT_ID()
     -->
    <insert id="insertUser" parameterType="cn.itheima.pojo.User" >
        <!-- 執行 select LAST_INSERT_ID()數據庫函數,返回自增的主鍵
        keyProperty:將返回的主鍵放入傳入參數的Id中保存.
        order:當前函數相對於insert語句的執行順序,在insert前執行是before,在insert后執行是AFTER
        resultType:id的類型,也就是keyproperties中屬性的類型
        -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
    
    <delete id="delUserById" parameterType="int">
        delete from user where id=#{id}
    </delete>
    
    <update id="updateUserById" parameterType="cn.itheima.pojo.User">
        update user set username=#{username} where id=#{id}
    </update>
</mapper>

加載映射文件 --mybatis框架需要加載映射文件,將User.xml添加在SqlMapConfig.xml

<!-- 加載映射文件 -->
    <mappers>
        <mapper resource="User.xml" />
    </mappers>

創建測試類UserTest進行測試

查詢單個User對象

@Test
    public void test1() throws IOException {
        // 核心配置文件
        String resource = "SqlMapConfig.xml";
        // 通過流將核心配置文件加載進來
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 通過配置文件創建會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        // 通過會話工廠獲取會話
        SqlSession openSession = factory.openSession();
        // 通過會話執行sql 第一個參數是名稱空間+SqlID 第二個參數表示sql執行需要的參數
        User user = openSession.selectOne("test.findUserById", 1);
        System.out.println(user.toString());
        // 關閉會話
        openSession.close();

    }

通過username進行模糊查詢

@Test
    public void test2() throws IOException {
        // 核心配置文件
        String resource = "SqlMapConfig.xml";
        // 通過流將核心配置文件加載進來
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 通過配置文件創建會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        // 通過會話工廠獲取會話
        SqlSession openSession = factory.openSession();
        // 調用User.xml中的魔化查詢方法 返回集合
        List<User> selectList = openSession.selectList("test.findUserByName", "張");
        // 循環結果
        System.out.println(selectList.size());
        for (User user : selectList) {
            System.out.println(user.toString());
        }
        // 關閉會話
        openSession.close();
    }

添加一條User用戶到數據庫

@Test
    public void test3() throws IOException {
        // 核心配置文件
        String resource = "SqlMapConfig.xml";
        // 通過流將核心配置文件加載進來
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 通過配置文件創建會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        // 通過會話工廠獲取會話
        SqlSession openSession = factory.openSession();
        // 創建需要插入的User對象
        User user = new User();
        user.setUsername("Jimisun");
        user.setSex("1");
        user.setAddress("北京");
        System.out.println("====插入前的User的id=" + user.getId());
        // 會話調用插入的sql
        openSession.insert("test.insertUser", user);
        // 默認mybatis自動開啟事務,需要手動提交事務
        openSession.commit();
        System.out.println("====插入后的User的id=" + user.getId());
        // 關閉會話
        openSession.close();
    }

刪除一條記錄

@Test
    public void test4() throws IOException {
        // 核心配置文件
        String resource = "SqlMapConfig.xml";
        // 通過流將核心配置文件加載進來
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 通過配置文件創建會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        // 通過會話工廠獲取會話
        SqlSession openSession = factory.openSession();
        // 會話執行sql操作
        openSession.delete("test.deleteUserById", 1);
        // 提交事務
        openSession.commit();
        // 關閉會話
        openSession.close();
    }

更新一條記錄

@Test
    public void test5() throws Exception {
        // 核心配置文件
        String resource = "SqlMapConfig.xml";
        // 通過流將核心配置文件加載進來
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 通過配置文件創建會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        // 通過會話工廠獲取會話
        SqlSession openSession = factory.openSession();
        //創建User對象
        User user = new User ();
        user.setId(1);
        user.setUsername("王麻子");
        openSession.update("test.updateByUserId", user);
        //提交事務
        openSession.commit();
        //關閉會話
        openSession.close();

    }

 5.使用MyBatis的開發方法

  • 原生Dao方法
    • UserDao  接口
    • UserDaoImpl  實現類
      • findUserById()  -----方法內使用MyBatis框架進行操作
        // 核心配置文件
                String resource = "SqlMapConfig.xml";
                // 通過流將核心配置文件加載進來
                InputStream inputStream = Resources.getResourceAsStream(resource);
                // 通過配置文件創建會話工廠
                SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
                // 通過會話工廠獲取會話
                SqlSession openSession = factory.openSession();
                // 通過會話執行sql 第一個參數是名稱空間+SqlID 第二個參數表示sql執行需要的參數
                User user = openSession.selectOne("test.findUserById", 1);
                System.out.println(user.toString());
                // 關閉會話
                openSession.close();
  • Mapper接口開發    ----Mapper接口開發方法只需要程序員編寫Mapper接口(相當於Dao接口),由Mybatis框架根據接口定義創建接口的動態代理對象,代理對象的方法體同上邊Dao接口實現類方法。
    • 開發規范
      • Mapper.xml文件中的namespace與mapper接口的類路徑相同。

      • Mapper接口方法名和Mapper.xml中定義的每個statement的id相同
      • Mapper接口方法的輸入參數類型和mapper.xml中定義的每個sql 的parameterType的類型相同

      • Mapper接口方法的輸出參數類型和mapper.xml中定義的每個sql的resultType的類型相同

    • 開發目錄
      • UserDao   接口 遵循上面規則
      • UserServiceImpl直接調用
            @Test
            public void testFindUserById() throws Exception{
                SqlSession openSession = factory.openSession();
                //通過getMapper方法來實例化接口
                UserMapper mapper = openSession.getMapper(UserMapper.class);
                
                User user = mapper.findUserById(1);
                System.out.println(user);
            }

 6.SqlMapConfig.xml配置文件

  • properties(屬性) 常用於加載配置文件
    <properties resource="db.properties"></properties>
    <environments default="development">
            <environment id="development">
            <!-- 使用jdbc事務管理-->
            <transactionManager type="JDBC" />
            <!-- 數據庫連接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
            </environment>
    </environments>
  • typeAliases(類型別名)

    <typeAliases> 
            <!-- 定義單個pojo類別名
            type:類的全路勁名稱
            alias:別名
             -->
            <typeAlias type="cn.itheima.pojo.User" alias="user"/> 
            
            <!-- 使用包掃描的方式批量定義別名 
            定以后別名等於類名,不區分大小寫,但是建議按照java命名規則來,首字母小寫,以后每個單詞的首字母大寫
            -->
            <package name="cn.itheima.pojo"/>
        </typeAliases>
  • mappers(映射器)

    • 相對於類路徑的資源
      <mapper resource="sqlmap/User.xml" />
    • 使用mapper接口開發
      <mapper class="cn.redrat.mybatis.mapper.UserMapper"/>
    • 注冊指定包下所有的mapper接口
      <package name="cn.redrat.mybatis.mapper"/>
      • 注意:此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中。

7.輸入映射和輸出映射

  • Mapper.xml映射文件中定義了操作數據庫的sql,每個sql是一個statement,映射文件是mybatis的核心。
    • parameterType(輸入類型)

      • 傳遞基本類型包含String
      • 傳遞pojo對象
      • 傳遞vo對象
    • resultType(輸出類型)

      • 返回pojo類型
      • 返回集合
      • 返回基本類型包含String

 

8.動態Sql --通過mybatis提供的各種標簽方法實現動態拼接sql

  • if
    <!-- 傳遞pojo綜合查詢用戶信息   注意要做不等於空字符串校驗-->
        <select id="findUserList" parameterType="user" resultType="user">
            select * from user 
            where 1=1 
            <if test="id!=null">
            and id=#{id}
            </if>
            <if test="username!=null and username!=''">
            and username like '%${username}%'
            </if>
    </select>
  • where
    <select id="findUserList" parameterType="user" resultType="user">
            select * from user 
            <where>
            <if test="id!=null and id!=''">
            and id=#{id}
            </if>
            <if test="username!=null and username!=''">
            and username like '%${username}%'
            </if>
            </where>
    </select

     where標簽的作用可以去掉sql語句中的where 1=1 並自動處理第一個 and

  • foreach
    <select id="findUserByIds" parameterType="cn.redrat.pojo.QueryVo" resultType="cn.redrat.pojo.User">
            select * from user
            <where>
                <if test="ids != null">
                    <!-- 
                    foreach:循環傳入的集合參數
                    collection:傳入的集合的變量名稱
                    item:每次循環將循環出的數據放入這個變量中
                    open:循環開始拼接的字符串
                    close:循環結束拼接的字符串
                    separator:循環中拼接的分隔符
                     -->
                    <foreach collection="ids" item="id" open="id in (" close=")" separator=",">
                        #{id}
                    </foreach>
                </if>
            </where>
        </select>

9.MyBatis關聯查詢核心示例

  • 一對一查詢
    <!-- 一對一:自動映射 -->
        <select id="findOrdersAndUser1" resultType="cn.redrat.pojo.CustomOrders">
            select a.*, b.id uid, username, birthday, sex, address 
            from orders a, user b 
            where a.user_id = b.id
        </select>
        
        <!-- 一對一:手動映射 -->
        <!-- 
        id:resultMap的唯一標識
        type:將查詢出的數據放入這個指定的對象中
        注意:手動映射需要指定數據庫中表的字段名與java中pojo類的屬性名稱的對應關系
         -->
        <resultMap type="cn.redrat.pojo.Orders" id="orderAndUserResultMap">
            <!-- id標簽指定主鍵字段對應關系
            column:列,數據庫中的字段名稱
            property:屬性,java中pojo中的屬性名稱
             -->
            <id column="id" property="id"/>
            
            <!-- result:標簽指定非主鍵字段的對應關系 -->
            <result column="user_id" property="userId"/>
            <result column="number" property="number"/>
            <result column="createtime" property="createtime"/>
            <result column="note" property="note"/>
            
            <!-- 這個標簽指定單個對象的對應關系 
            property:指定將數據放入Orders中的user屬性中
            javaType:user屬性的類型
            -->
            <association property="user" javaType="cn.redrat.pojo.User">
                <id column="uid" property="id"/>
                <result column="username" property="username"/>
                <result column="birthday" property="birthday"/>
                <result column="sex" property="sex"/>
                <result column="address" property="address"/>
            </association>
        </resultMap>
        <select id="findOrdersAndUser2" resultMap="orderAndUserResultMap">
            select a.*, b.id uid, username, birthday, sex, address 
            from orders a, user b 
            where a.user_id = b.id
        </select>
  • 一對多
    <resultMap type="cn.redrat.pojo.User" id="userAndOrdersResultMap">
            <id column="id" property="id"/>
            <result column="username" property="username"/>
            <result column="birthday" property="birthday"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
            
            <!-- 指定對應的集合對象關系映射
            property:將數據放入User對象中的ordersList屬性中
            ofType:指定ordersList屬性的泛型類型
             -->
            <collection property="ordersList" ofType="cn.redrat.pojo.Orders">
                <id column="oid" property="id"/>
                <result column="user_id" property="userId"/>
                <result column="number" property="number"/>
                <result column="createtime" property="createtime"/>
            </collection>
        </resultMap>
        <select id="findUserAndOrders" resultMap="userAndOrdersResultMap">
            select a.*, b.id oid ,user_id, number, createtime 
            from user a, orders b where a.id = b.user_id
        </select>

     


免責聲明!

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



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