1. 程式人生 > >Mybatis第一篇【介紹、快速入門、工作流程】

Mybatis第一篇【介紹、快速入門、工作流程】

什麼是MyBatis

MyBatis 本是apache的一個開源專案iBatis, 2010年這個專案由apache software foundation 遷移到了google code,並且改名為MyBatis。是一個基於Java的持久層框架

為什麼我們要用Mybatis?

無論是Mybatis、Hibernate都是ORM的一種實現框架,都是對JDBC的一種封裝!

這裡寫圖片描述

到目前為止,我們已經在持久層中學了幾種技術了…

  • Hibernate
  • jdbc
  • SpringDAO

那我們為啥還要學Mybatis呢???現在Mybatis在業內大行其道,那為啥他能那麼火呢??

Hibernate是一個比較老舊的框架,用過他的同學都知道,只要你會用,用起來十分舒服…啥sql程式碼都不用寫…但是呢,它也是有的缺點::處理複雜業務時,靈活度差, 複雜的HQL難寫難理解,例如多表查詢的HQL語句

而JDBC很容易理解,就那麼幾個固定的步驟,就是開發起來太麻煩了,因為什麼都要我們自己幹..

而SpringDAO其實就是JDBC的一層封裝,就類似於dbutils一樣,沒有特別出彩的地方….

我們可以認為,Mybatis就是jdbc和Hibernate之間的一個平衡點…畢竟現在業界都是用這個框架,我們也不能不學呀!

Mybatis快速入門

其實我們已經學過了Hibernate了,對於Mybatis入門其實就非常類似的。因此就很簡單就能掌握基本的開發了…

匯入開發包

匯入Mybatis開發包

  • mybatis-3.1.1.jar
  • commons-logging-1.1.1.jar
  • log4j-1.2.16.jar
  • cglib-2.2.2.jar
  • asm-3.3.1.jar

匯入mysql/oracle開發包

  • mysql-connector-java-5.1.7-bin.jar
  • Oracle 11g 11.2.0.1.0 JDBC_ojdbc6.jar

準備測試工作

建立一張表


create table students(
  id  int(5) primary key,
  name varchar(10),
  sal double(8,2)
);

建立實體:


/**
 * Created by ozc on 2017/7/21.
 */

public
class Student { private Integer id; private String name; private Double sal; public Student() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getSal() { return sal; } public void setSal(Double sal) { this.sal = sal; } }

建立mybatis配置檔案

建立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>


    <!-- 載入類路徑下的屬性檔案 -->
    <properties resource="db.properties"/>

    <!-- 設定一個預設的連線環境資訊 -->
    <environments default="mysql_developer">
        <!-- 連線環境資訊,取一個任意唯一的名字 -->
        <environment id="mysql_developer">
            <!-- mybatis使用jdbc事務管理方式 -->
            <transactionManager type="jdbc"/>
            <!-- mybatis使用連線池方式來獲取連線 -->
            <dataSource type="pooled">
                <!-- 配置與資料庫互動的4個必要屬性 -->
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.password}"/>
            </dataSource>
        </environment>


        <!-- 連線環境資訊,取一個任意唯一的名字 -->
        <environment id="oracle_developer">
            <!-- mybatis使用jdbc事務管理方式 -->
            <transactionManager type="jdbc"/>
            <!-- mybatis使用連線池方式來獲取連線 -->
            <dataSource type="pooled">
                <!-- 配置與資料庫互動的4個必要屬性 -->
                <property name="driver" value="${oracle.driver}"/>
                <property name="url" value="${oracle.url}"/>
                <property name="username" value="${oracle.username}"/>
                <property name="password" value="${oracle.password}"/>
            </dataSource>
        </environment>
    </environments>


</configuration>

編寫工具類測試是否獲取到連線

使用Mybatis的API來建立一個工具類,通過mybatis配置檔案與資料庫的資訊,得到Connection物件


package cn.itcast.javaee.mybatis.util;

import java.io.IOException;
import java.io.Reader;
import java.sql.Connection;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 * 工具類
 * @author AdminTC
 */
public class MybatisUtil {
    private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
    private static SqlSessionFactory sqlSessionFactory;
    /**
     * 載入位於src/mybatis.xml配置檔案
     */
    static{
        try {
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    /**
     * 禁止外界通過new方法建立 
     */
    private MybatisUtil(){}
    /**
     * 獲取SqlSession
     */
    public static SqlSession getSqlSession(){
        //從當前執行緒中獲取SqlSession物件
        SqlSession sqlSession = threadLocal.get();
        //如果SqlSession物件為空
        if(sqlSession == null){
            //在SqlSessionFactory非空的情況下,獲取SqlSession物件
            sqlSession = sqlSessionFactory.openSession();
            //將SqlSession物件與當前執行緒繫結在一起
            threadLocal.set(sqlSession);
        }
        //返回SqlSession物件
        return sqlSession;
    }
    /**
     * 關閉SqlSession與當前執行緒分開
     */
    public static void closeSqlSession(){
        //從當前執行緒中獲取SqlSession物件
        SqlSession sqlSession = threadLocal.get();
        //如果SqlSession物件非空
        if(sqlSession != null){
            //關閉SqlSession物件
            sqlSession.close();
            //分開當前執行緒與SqlSession物件的關係,目的是讓GC儘早回收
            threadLocal.remove();
        }
    }   
    /**
     * 測試
     */
    public static void main(String[] args) {
        Connection conn = MybatisUtil.getSqlSession().getConnection();
        System.out.println(conn!=null?"連線成功":"連線失敗");
    }
}



建立實體與對映關係檔案

配置實體與表的對映關係


<?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屬性是名稱空間,必須唯一 -->
<mapper namespace="cn.itcast.javaee.mybatis.app04.Student"> 

    <!-- resultMap標籤:對映實體與表 
         type屬性:表示實體全路徑名
         id屬性:為實體與表的對映取一個任意的唯一的名字
    -->
    <resultMap type="student" id="studentMap">
        <!-- id標籤:對映主鍵屬性
             result標籤:對映非主鍵屬性
             property屬性:實體的屬性名
             column屬性:表的欄位名  
        -->                         
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sal" column="sal"/>
    </resultMap>

</mapper>

現在我們已經有了Mybatis的配置檔案和表與實體之前的對映檔案了,因此我們要將配置檔案和對映檔案關聯起來


    <mappers>
        <mapper resource="StudentMapper.xml"/>
    </mappers>

在測試類上,我們是可以獲取得到連線的

這裡寫圖片描述

編寫DAO


public class StudentDao {


    public void add(Student student) throws Exception {
        //得到連線物件
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        sqlSession.insert();
    }

    public static void main(String[] args) throws Exception {

        StudentDao studentDao = new StudentDao();

        Student student = new Student(1, "zhongfucheng", 10000D);
        studentDao.add(student);

    }
}

到現在為止,我們實體與表的對映檔案僅僅映射了實體屬性與表的欄位的關係…

我們在Hibernate中如果想要插入資料什麼的,只要呼叫save()方法就行了。Hibernate是自動化遮蔽掉了資料庫的差異,而我們Mybatis是需要自己手動編寫SQL程式碼的

那麼SQL程式碼是寫在哪裡的呢???明顯地,我們作為一個框架,不可能在程式中寫SQL,我們是在實體與表的對映檔案中寫的!

Mybatis實體與表的對映檔案中提供了insert標籤【SQL程式碼片段】供我們使用


    //在JDBC中我們通常使用?號作為佔位符,而在Mybatis中,我們是使用#{}作為佔位符
    //parameterType我們指定了傳入引數的型別
    //#{}實際上就是呼叫了Student屬性的get方法

    <insert id="add" parameterType="Student">

        INSERT INTO ZHONGFUCHENG.STUDENTS (ID, NAME, SAL) VALUES (#{id},#{name},#{sal});
    </insert>

在程式中呼叫對映檔案的SQL程式碼片段


    public void add(Student student) throws Exception {
        //得到連線物件
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //對映檔案的名稱空間.SQL片段的ID,就可以呼叫對應的對映檔案中的SQL
            sqlSession.insert("StudentID.add", student);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

值得注意的是:Mybatis中的事務是預設開啟的,因此我們在完成操作以後,需要我們手動去提交事務!

Mybatis工作流程

  • 通過Reader物件讀取Mybatis對映檔案
  • 通過SqlSessionFactoryBuilder物件建立SqlSessionFactory物件
  • 獲取當前執行緒的SQLSession
  • 事務預設開啟
  • 通過SQLSession讀取對映檔案中的操作編號,從而讀取SQL語句
  • 提交事務
  • 關閉資源