MyBatis入門第1天--MyBatis基礎知識(一)

文檔版本 開發工具 測試平臺 工程名字 日期 作者 備註
V1.0 2016.06.25 lutianfei none

  • 內容梳理

  • 第一天:基礎知識(重點,內容量多)

    • 對原生態jdbc程序(單獨使用jdbc開發)問題總結
    • mybatis框架原理 (掌握)
    • mybatis入門程序
    • 用戶的增、刪、改、查
    • mybatis開發dao兩種方法:
    • 原始dao開發方法(程序需要編寫dao接口和dao實現類)(掌握)
    • mybaits的mapper接口(相當於dao接口)代理開發方法(掌握)
    • mybatis配置文件SqlMapConfig.xml
    • mybatis核心:
    • mybatis輸入映射(掌握)
    • mybatis輸出映射(掌握)
    • mybatis的動態sql(掌握)
  • 第二天:高級知識

    • 訂單商品數據模型分析
    • 高級結果集映射(一對一、一對多、多對多)
    • mybatis延遲加載
    • mybatis查詢緩存(一級緩存、二級緩存)
    • mybaits和spring進行整合(掌握)
    • mybatis逆向工程
  • POJO : 名稱解釋

    • POJO(Plain Ordinary Java Object)簡單的Java對象,實際就是普通JavaBeans,是爲了避免和EJB混淆所創造的簡稱。
    • 使用POJO名稱是爲了避免和EJB混淆起來, 而且簡稱比較直接. 其中有一些屬性及其getter setter方法的類,沒有業務邏輯,有時可以作爲VO(value -object)或dto(Data Transform Object)來使用.當然,如果你有一個簡單的運算屬性也是可以的,但不允許有業務方法,也不能攜帶有connection之類的方法。


原生態jdbc程序中問題總結

  • 1、數據庫連接,使用時就創建,不使用立即釋放,對數據庫進行頻繁連接開啓和關閉,造成數據庫資源浪費,影響 數據庫性能。

    • 設想:使用數據庫連接池管理數據庫連接。
  • 2、將sql語句硬編碼到java代碼中,如果sql 語句修改,需要重新編譯java代碼,不利於系統維護。

    • 設想:將sql語句配置在xml配置文件中,即使sql變化,不需要對java代碼進行重新編譯。
  • 3、向preparedStatement中設置參數,對佔位符號位置和設置參數值,硬編碼在java代碼中,不利於系統維護。

    • 設想:將sql語句及佔位符號和參數全部配置在xml中。
  • 4、從resutSet中遍歷結果集數據時,存在硬編碼,將獲取表的字段進行硬編碼,不利於系統維護。

    • 設想:將查詢的結果集,自動映射成java對象。


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可以將向 preparedStatement中的輸入參數自動進行輸入映射,將查詢結果集靈活映射成java對象。(輸出映射)

  • MyBatis框架示意圖

  • mapper.xml文件即sql映射文件,文件中配置了操作數據庫的sql語句。此文件需要在SqlMapConfig.xml中加載。

  • 通過mybatis環境等配置信息構造SqlSessionFactory即會話工廠

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

  • mybatis底層自定義了Executor執行器接口操作數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器。

  • Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sql的id即是Mapped statement的id。

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

  • Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql後將輸出結果映射至java對象中,輸出結果映射過程相當於jdbc編程中對結果的解析處理過程。



MyBatis入門程序

  • 需求

    • 根據用戶id(主鍵)查詢用戶信息
    • 根據用戶名稱模糊查詢用戶信息
    • 添加用戶
    • 刪除用戶
    • 更新用戶
  • 3.1 環境

    • java環境:jdk1.7.0_72
    • eclipse:indigo
    • mysql:5.1
  • mybatis運行環境(jar包):

  • lib下:依賴包

    • mybatis-3.2.7.jar:核心包
    • mybatis-3.2.7.pdf,操作指南

創建mysql數據庫

  • 先導入sql_table.sql,再導入 sql_data.sql腳本

    • sql_table.sql:記錄表結構
    • sql_data.sql:記錄測試數據,在實際企業開發中,最後提供一個初始化數據腳本
  • log4j.properties

# Global logging configuration
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
  • 工程結構

  • SqlMapConfig.xml

    • 配置Mybatis的運行環境,數據源、事務等。

<?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>

<!-- </a>和spring整合後 environments配置將廢除-->
   <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="mysql" />
         </dataSource>

      </environment>
   </environments>
</configuration>


根據用戶id(主鍵)查詢用戶信息

創建po類
  • Po類作爲mybatis進行sql映射使用,po類通常與數據庫表對應,User.java如下:
Public class User {
   private int id;
   private String username;// 用戶姓名
   private String sex;// 性別
   private Date birthday;// 生日
   private String address;// 地址

get/set... toString


映射文件
  • 映射文件命名:

    • User.xml(原始ibatis命名)
    • MyBatis的mapper代理開發映射文件名稱叫XXXMapper.xml
      • 比如:UserMapper.xml、ItemsMapper.xml
  • 在映射文件中配置sql語句

    • 在classpath下的sqlmap目錄下創建sql映射文件Users.xml:
    • namespace : 命名空間,用於隔離sql語句,後面會講另一層非常重要的作用。
  • 配置參數說明

    • id:標識 映射文件中的 sql 將sql語句封裝到mappedStatement對象中,所以將id稱爲statement的id
    • parameterType:指定輸入 參數的類型,這裏指定int型
    • #{}表示一個佔位符號
      • #{id}:其中的id表示接收輸入 的參數,參數名稱就是id,如果輸入 參數是簡單類型,#{}中的參數名可以任意,可以value或其它名稱
    • resultType:指定sql輸出結果的所映射的java對象類型,select指定resultType表示將單條記錄映射成的java對象。
<?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進行分類化管理,理解sql隔離 
注意:使用mapper代理方法開發,namespace有特殊重要的作用
-->
<mapper namespace="test">

    <!-- 在 映射文件中配置很多sql語句 -->
    <!-- 需求:通過id查詢用戶表的記錄 -->
    <!-- 通過 select執行數據庫查詢
    id:標識 映射文件中的 sql
    將sql語句封裝到mappedStatement對象中,所以將id稱爲statement的id
    parameterType:指定輸入 參數的類型,這裏指定int型 
    #{}表示一個佔位符號
    #{id}:其中的id表示接收輸入 的參數,參數名稱就是id,如果輸入 參數是簡單類型,#{}中的參數名可以任意,可以value或其它名稱

    resultType:指定sql輸出結果 的所映射的java對象類型,select指定resultType表示將單條記錄映射成的java對象。
     -->
    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
        SELECT * FROM USER WHERE id=#{value}
    </select>


在SqlMapConfig.xml加載映射文件
  • 在sqlMapConfig.xml中加載User.xml;
  • parameterType:定義輸入到sql中的映射類型,#{id}表示使用preparedstatement設置佔位符號並將輸入變量id傳到sql。
  • resultType:定義結果映射類型。

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

        <!--通過resource方法一次加載一個映射文件 -->
        <!-- <mapper resource="mapper/UserMapper.xml"/> -->
    </mappers>


測試程序編寫
public class MybatisFirst {

    // 根據id查詢用戶信息,得到一條記錄結果
    @Test
    public void findUserByIdTest() throws IOException {

        // mybatis配置文件
        String resource = "SqlMapConfig.xml";
        // 得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 創建會話工廠,傳入mybatis的配置文件信息
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);

        // 通過工廠得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 通過SqlSession操作數據庫
        // 第一個參數:映射文件中statement的id,等於=namespace+"."+statement的id
        // 第二個參數:指定和映射文件中所匹配的parameterType類型的參數
        // sqlSession.selectOne結果 是與映射文件中所匹配的resultType類型的對象
        // selectOne查詢出一條記錄
        User user = sqlSession.selectOne("test.findUserById", 1);

        System.out.println(user);

        // 釋放資源
        sqlSession.close();

    }
}


根據用戶名稱模糊查詢用戶信息

映射文件
  • 使用User.xml,添加根據用戶名稱模糊查詢用戶信息的sql語句。
    • resultType:指定就是單條記錄所映射的java對象 類型
    • ${}:表示拼接sql串,將接收到參數的內容不加任何修飾拼接在sql中。
      • 使用${}拼接sql,會引起sql注入
    • value {}中只能使用value
<!-- 根據用戶名稱模糊查詢用戶信息,可能返回多條
    resultType:指定就是單條記錄所映射的java對象 類型
    ${}:表示拼接sql串,將接收到參數的內容不加任何修飾拼接在sql中。
    使用${}拼接sql,引起 sql注入
    ${value}:接收輸入 參數的內容,如果傳入類型是簡單類型,${}中只能使用value
     -->
    <select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
        SELECT * FROM USER WHERE username LIKE '%${value}%'
    </select>


程序代碼
// 根據用戶名稱模糊查詢用戶列表
    @Test
    public void findUserByNameTest() throws IOException {
        // mybatis配置文件
        String resource = "SqlMapConfig.xml";
        // 得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 創建會話工廠,傳入mybatis的配置文件信息
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);

        // 通過工廠得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // list中的user和映射文件中resultType所指定的類型一致
        List<User> list = sqlSession.selectList("test.findUserByName", "小明");
        System.out.println(list);
        sqlSession.close();

    }


  • 知識點回顧

  • #{}${}

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

    • parameterType:指定輸入參數類型,mybatis通過ognl從輸入對象中獲取參數值拼接在sql中。
    • resultType:指定輸出結果類型,mybatis將sql查詢結果的一行記錄數據映射爲resultType指定類型的對象。
  • selectOne和selectList

    • selectOne查詢一條記錄,如果使用selectOne查詢多條記錄則拋出異常:
      • org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3 at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
    • selectList可以查詢一條或多條記錄。


添加用戶

  • 在 User.xml中配置添加用戶的Statement


  • 程序代碼
// 添加用戶信息
    @Test
    public void insertUserTest() throws IOException {
        // mybatis配置文件
        String resource = "SqlMapConfig.xml";
        // 得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 創建會話工廠,傳入mybatis的配置文件信息
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);

        // 通過工廠得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 插入用戶對象
        User user = new User();
        user.setUsername("王小軍");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("河南鄭州");

        sqlSession.insert("test.insertUser", user);

        // 提交事務
        sqlSession.commit();

        // 獲取用戶信息主鍵
        System.out.println(user.getId());
        // 關閉會話
        sqlSession.close();

    }
  • 自增主鍵返回
  • mysql自增主鍵,執行insert提交之前自動生成一個自增主鍵。
  • 通過mysql函數獲取到剛插入記錄的自增主鍵:

    • LAST_INSERT_ID()
    • 是insert之後調用此函數。
  • 將插入數據的主鍵返回,返回到user對象中

    • SELECT LAST_INSERT_ID():得到剛insert進去記錄的主鍵值,只適用與自增主鍵
    • keyProperty:將查詢到主鍵值設置到parameterType指定的對象的哪個屬性
    • order:SELECT LAST_INSERT_ID()執行順序,相對於insert語句來說它的執行順序
    • resultType:指定SELECT LAST_INSERT_ID()的結果類型
  • 修改insertUser定義:

    <!-- 添加用戶 
    parameterType:指定輸入 參數類型是pojo(包括 用戶信息)
    #{}中指定pojo的屬性名,接收到pojo對象的屬性值,mybatis通過OGNL獲取對象的屬性值
    -->
    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
        <!-- 
        將插入數據的主鍵返回,返回到user對象中

        SELECT LAST_INSERT_ID():得到剛insert進去記錄的主鍵值,只適用與自增主鍵

        keyProperty:將查詢到主鍵值設置到parameterType指定的對象的哪個屬性
        order:SELECT LAST_INSERT_ID()執行順序,相對於insert語句來說它的執行順序
        resultType:指定SELECT LAST_INSERT_ID()的結果類型
         -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>
        insert into user ( username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})

    </insert>


  • 非自增主鍵返回(使用uuid())
  • 使用mysql的uuid()函數生成主鍵,需要修改表中id字段類型爲string,長度設置成35位。

  • 執行思路:

    • 先通過uuid()查詢到主鍵,將主鍵輸入 到sql語句中。
    • 執行uuid()語句順序相對於insert語句之前執行。
<!-- 
使用mysql的uuid()生成主鍵
執行過程:
首先通過uuid()得到主鍵,將主鍵設置到user對象的id屬性中
其次在insert執行時,從user對象中取出id屬性值
 -->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
    SELECT uuid()
</selectKey>
insert into user ( id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})
  • 通過oracle的序列生成主鍵:
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT 序列名.nextval()
</selectKey>
insert into user ( id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})

刪除用戶

  • 映射文件
    <!-- 刪除 用戶
    根據id刪除用戶,需要輸入 id值
     -->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>
  • 代碼
// 根據id刪除 用戶信息
    @Test
    public void deleteUserTest() throws IOException {
        // mybatis配置文件
        String resource = "SqlMapConfig.xml";
        // 得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 創建會話工廠,傳入mybatis的配置文件信息
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);

        // 通過工廠得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 傳入id刪除 用戶
        sqlSession.delete("test.deleteUser", 39);

        // 提交事務
        sqlSession.commit();

        // 關閉會話
        sqlSession.close();

    }


更新用戶

  • 映射文件
<!-- 根據id更新用戶
分析:
需要傳入用戶的id
需要傳入用戶的更新信息
parameterType指定user對象,包括 id和更新信息,注意:id必須存在
#{id}:從輸入 user對象中獲取id屬性值
 -->
<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
    update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} 
     where id=#{id}
</update>


  • 代碼
    // 更新用戶信息
    @Test
    public void updateUserTest() throws IOException {
        // mybatis配置文件
        String resource = "SqlMapConfig.xml";
        // 得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 創建會話工廠,傳入mybatis的配置文件信息
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);

        // 通過工廠得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 更新用戶信息

        User user = new User();
        //必須設置id
        user.setId(41);
        user.setUsername("王大軍");
        user.setBirthday(new Date());
        user.setSex("2");
        user.setAddress("河南鄭州");

        sqlSession.update("test.updateUser", user);

        // 提交事務
        sqlSession.commit();

        // 關閉會話
        sqlSession.close();

    }

入門程序總結

  • parameterType
    • 在映射文件中通過parameterType指定輸入 參數的類型。
  • resultType

    • 在映射文件中通過resultType指定輸出結果的類型。
  • #{}${}

    • #{}表示一個佔位符號#{}接收輸入參數,類型可以是簡單類型,pojo、hashmap。
      • 如果接收簡單類型,#{}中可以寫成value或其它名稱。
    • #{}接收pojo對象值,通過OGNL讀取對象中的屬性值,通過屬性.屬性.屬性…的方式獲取對象屬性值。
    • ${}表示一個拼接符號,會引用sql注入,所以不建議使用${}
    • ${}接收輸入參數,類型可以是簡單類型,pojo、hashmap。
    • 如果接收簡單類型,${}中只能寫成value。
    • ${}接收pojo對象值,通過OGNL讀取對象中的屬性值,通過屬性.屬性.屬性…的方式獲取對象屬性值。




mybatis和hibernate本質區別和應用場景

  • hibernate:是一個標準ORM框架(對象關係映射)。入門門檻較高的,不需要程序寫sql,sql語句自動生成了。對sql語句進行優化、修改比較困難的。
  • 應用場景:

    • 適用與需求變化不多的中小型項目,比如:後臺管理系統,erp、orm、oa。。
  • mybatis:專注是sql本身,需要程序員自己編寫sql語句,sql修改、優化比較方便。mybatis是一個不完全 的ORM框架,雖然程序員自己寫sql,mybatis 也可以實現映射(輸入映射、輸出映射)。

  • 應用場景:

    • 適用與需求變化較多的項目,比如:互聯網項目。
  • 企業進行技術選型,以低成本 高回報作爲技術選型的原則,根據項目組的技術力量進行選擇。




發佈了91 篇原創文章 · 獲贊 177 · 訪問量 43萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章