1. 程式人生 > >Mybatis學習記錄(一)--Mybatis入門

Mybatis學習記錄(一)--Mybatis入門

一.傳統資料庫解決方案

對於資料庫的連線,在java中簡單的就是直接使用JDBC來控制資料庫.傳統的jdbc方式按照以下幾步來操作資料庫.

1.載入驅動 2. 建立並獲取連線 3. 建立jdbc statement物件 4.設定sql語句 5.設定sql語句引數
6.執行sql並返回resultset結果 7.取出結果並釋放連線

傳統的方法存在以下幾點問題:
1. 資料庫連結建立、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用資料庫連結池可解決此問題。
2. Sql語句在程式碼中硬編碼,造成程式碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java程式碼。
3.

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

那麼mybatis等框架的出現就是用來解決這些問題,解決方案就是重新對jdbc進行封裝.

二.mybatis介紹

MyBatis 本是apache的一個開源專案iBatis, 2010年這個專案由apache software foundation 遷移到了google code,並且改名為MyBatis,實質上Mybatis對ibatis進行一些改進。
MyBatis是一個優秀的持久層框架,它對jdbc的操作資料庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設定引數、結果集檢索等jdbc繁雜的過程程式碼。
Mybatis通過xml或註解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,並通過java物件和statement中的sql進行對映生成最終執行的sql語句,最後由mybatis框架執行sql並將結果對映成java物件並返回。

三.mybatis整體結構

這裡寫圖片描述

1. SqlMapConfig.xml:mybatis的全域性配置檔案,配置了mybatis的執行環境等資訊。
mapper.xml檔案即sql對映檔案,檔案中配置了操作資料庫的sql語句。此檔案需要在SqlMapConfig.xml中載入。
2. SqlSessionFactry:會話工廠,用於建立會話
3. SqlSession:會話,主要來進行資料庫操作
4. Executor: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通過Mapped Statement在執行sql後將輸出結果對映至java物件中,輸出結果對映過程相當於jdbc程式設計中對結果的解析處理過程。

四.mybatis下載

五.mybatis入門程式

1.基本配置

首先匯入mysql的包,mybatis的包,log4j的包

為了演示入門程式效果,所以在資料庫中建立一張User表
這裡寫圖片描述

在程式碼中寫上model類

public class User {
    private int id;
    private String username;
    private String password;
    private String nickname;
    private int status;

    //省略get和set方法

    @Override
    public String toString() {
        return "id:"+id+"username:"+username+"password:"+password+"nickname:"+nickname;
    }
}

2.配置log4j

使用log4j可以在除錯mybatis的過程中省去很多麻煩,還可以直觀的看到mybatis的sql語句.
首先把log4j的jar包匯入到專案中,然後建立log4j.properties檔案,按照官方文件寫入配置


# Global logging configuration
#在開發環境中要設定為DEBUG,不然不會打印出資訊
log4j.rootLogger=DEBUG, stdout
# 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

這樣在執行過程中mybatis就會在控制檯打出相應的日誌了.

3.配置SqlMapConfig.xml

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>
    <!-- 和spring整合後 environments配置將廢除,交給spring管理-->
    <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/shopdemo?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="7946521" />
            </dataSource>
        </environment>
    </environments>

    <!--配置mappeer對映-->
    <mappers>
        <mapper resource="mapper/User.xml"/>
    </mappers>

</configuration>

4.根據id查詢使用者(精確查詢單條資料)

根據mybatis整體流程,配置完SqlMapConfig.xml之後是建立相應的model類的對映.這裡我們為User建立User.xml檔案,並寫上sql語句

<?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">
<!--名稱空間,用於隔離sql語句,後面會講另一層非常重要的作用。-->
<mapper namespace="test">
    <!--根據id查詢出使用者資訊(查詢一條資料)-->
    <select id="findUserById" parameterType="int" resultType="com.aust.model.User">
        SELECT * FROM user WHERE id=#{id}
    </select>
</mapper>
  • id:標識當前sql,mybatis把sql語句封裝到MappedStatement中,所以可以稱為Statement的唯一標識
  • parameterType:指定輸入引數型別,mybatis通過ognl從輸入物件中獲取引數值拼接在sql中。
  • resultType:指定輸出結果型別,mybatis將sql查詢結果的一行記錄資料對映為resultType指定型別的物件。select下指定將單條資料對映成java物件

接下來在SqlMapConfig.xml中配置mapper對映,再其裡面加入下面配置

<!--配置mappeer對映-->
    <mappers>
        <mapper resource="mapper/User.xml"/>
    </mappers>

然後寫junit測試

    //測試取出單個
    @Test
    public void findUserTest(){
        //用於載入mybatis配置檔案的輸入流
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("SqlMapperConfig.xml");

        } catch (IOException e) {
            System.out.println("載入mybatis配置檔案出錯");
            e.printStackTrace();
        }
        //獲取會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //獲取會話
        SqlSession session = factory.openSession();
        //執行查詢單條記錄,返回的型別就是resultType
        //第一個引數命名規則為: 名稱空間+Statement id
        User u = session.selectOne("test.findUserById",1);
        //查詢完要釋放會話
        session.close();
        System.out.println(u.toString());
    }

結果
這裡寫圖片描述

5.根據姓名查詢使用者(模糊查詢多條資料)

和上面一樣的操作,先寫sql語句

<!--根據名稱進行模糊查詢(查詢出多條資料)-->
    <select id="findUserByName" parameterType="java.lang.String" resultType="com.aust.model.User">
    <!--markdown顯示不出來美元符號,,,-->
    SELECT * from user WHERE nickname LIKE '%美元符號{value}%'
    </select>

這裡和上面區別大的是使用了${}來配置,不過本質都是ognl來獲取的

  • #{}表示一個佔位符號,通過#{}可以實現preparedStatement向佔位符中設定值,自動進行java型別和jdbc型別轉換,#{}可以有效防止sql注入。 #{}可以接收簡單型別值或pojo屬性值。 如果parameterType傳輸單個簡單型別值,#{}括號中可以是value或其它名稱。
  • 美元符號{}表示拼接sql串,通過美元符號{}可以將parameterType傳入的內容拼接在sql中且不進行jdbc型別轉換, 所以可能引起sql注入,美元符號{}可以接收簡單型別值或pojo屬性值,如果parameterType傳輸單個簡單型別值,美元符號{}括號中只能是value。

寫junit測試類

    //測試取出多個
    @Test
    public void findUserByNameTest(){
        //用於載入mybatis配置檔案的輸入流
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("SqlMapperConfig.xml");

        } catch (IOException e) {
            System.out.println("載入mybatis配置檔案出錯");
            e.printStackTrace();
        }
        //獲取會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //獲取會話
        SqlSession session = factory.openSession();
        //查詢多條資料返回值為list集合,list裡面的型別是resultType配置的型別
        List<User> users = session.selectList("test.findUserByName","張");
        session.close();
        System.out.println(users);
    }

測試結果
這裡寫圖片描述

6.插入一個使用者,並返回自增主鍵

自增主鍵的返回,可以使用mysql的SELECT last_insert_id()函式,不過該sql要在insert語句之後才能執行

    <!--插入一個使用者-->
    <insert id="insertUser" parameterType="com.aust.model.User">
      <selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER" >
          SELECT last_insert_id()
      </selectKey>
        INSERT INTO user(username,password,nickname,status) VALUE (#{username},#{password},#{nickname},#{status})
    </insert>
  • keyProperty:返回的主鍵儲存在pojo中的哪個屬性
  • order:selectKey的執行順序,是相對與insert語句來說,由於mysql的自增原理執行完insert語句之後才將主鍵生成,所以這裡selectKey的執行順序為after
  • resultType:返回的主鍵是什麼型別
  • LAST_INSERT_ID():是mysql的函式,返回auto_increment自增列新記錄id值。

junit測試

//測試插入資料
    @Test
    public void insertUserTest(){
        //用於載入mybatis配置檔案的輸入流
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("SqlMapperConfig.xml");

        } catch (IOException e) {
            System.out.println("載入mybatis配置檔案出錯");
            e.printStackTrace();
        }
        //獲取會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //獲取會話
        SqlSession session = factory.openSession();
        User u = new User();
        u.setUsername("niuli");
        u.setPassword("123456");
        u.setNickname("牛李");
        u.setStatus(2);
        //返回的是受影響的行數
        int a = session.insert("test.insertUser",u);
        System.out.println(a);
        //提交事務
        session.commit();
        session.close();
        //獲取主鍵
        System.out.println("u id"+u.getId());
    }

測試結果
這裡寫圖片描述

7.mybatis對於非自增主鍵

非自增主鍵和自增主鍵差不多,只是獲取的函式和方式不同

需要增加通過select uuid()得到uuid值

<insert  id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey resultType="java.lang.String" order="BEFORE" 
keyProperty="id">
select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address) 
         values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
注意這裡使用的order是“BEFORE

8.更新和刪除使用者

更新和刪除操作差不多,就一起寫了

<!--刪除一個使用者-->
    <delete id="deleteUser" parameterType="int">
      DELETE FROM user WHERE id =#{id}
    </delete>
    <!--更新使用者-->
    <update id="updateUser" parameterType="com.aust.model.User">
      UPDATE user SET username=#{username},password=#{password},nickname=#{nickname} WHERE id = #{id}
    </update>

junit測試

//測試刪除使用者
    @Test
    public void deleteUserTest(){
        //用於載入mybatis配置檔案的輸入流
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("SqlMapperConfig.xml");

        } catch (IOException e) {
            System.out.println("載入mybatis配置檔案出錯");
            e.printStackTrace();
        }
        //獲取會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //獲取會話
        SqlSession session = factory.openSession();
        //返回的是受影響的行數
        int a = session.delete("test.deleteUser",10);
        System.out.println(a);
        //提交事務
        session.commit();
        session.close();
    }

    //測試更新使用者
    @Test
    public void updateUserTest(){
        //用於載入mybatis配置檔案的輸入流
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("SqlMapperConfig.xml");

        } catch (IOException e) {
            System.out.println("載入mybatis配置檔案出錯");
            e.printStackTrace();
        }
        //獲取會話工廠
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //獲取會話
        SqlSession session = factory.openSession();
        User u = new User();
        u.setId(1);
        u.setUsername("niuli");
        u.setPassword("123456");
        u.setNickname("牛李");
        u.setStatus(2);
        //返回的是受影響的行數
        int a = session.update("test.updateUser",u);
        System.out.println(a);
        //提交事務
        session.commit();
        session.close();
        //獲取主鍵
    }

一個mybatis的基本入門程式結束,專案結構如下
這裡寫圖片描述

專案示例: