MyBatis筆記一:GettingStart

MyBatis筆記一:GettingStart

1.MyBatis優(yōu)點

image

我們的工具和各種框架的作用就是為了我們操作數(shù)據(jù)庫簡潔凹耙,對于一些數(shù)據(jù)庫的工具能幫我們少寫一些處理異常等等的代碼滞诺,但是他們并不是自動化的藏澳,很多的操作還是需要我們自己進行,所以我們的框架就幫我們把中間黑色的部分封裝起來了删豺,減少我們的負擔(dān)遭贸,但是SQL也是重中之重掖疮,我們需要把這些東西自己來控制就有 MyBatis 這個半自動框架,以及我們需要學(xué)習(xí)更多的關(guān)于 HQL 的內(nèi)容扎瓶。

相對于Hibernate 他的優(yōu)點就是可以進行SQL 的定制化所踊,能讓我們的SQL更加優(yōu)化,雖然 Hibernate 也可以這么做但是有一點就是我們需要在原來的框架的基礎(chǔ)上學(xué)習(xí)更多的 HQL 相關(guān)的東西栗弟,加重學(xué)習(xí)負擔(dān)污筷。

2.Getting Start

1.引入依賴

首先我們需要建立一個新的工程,第一步就是進入 MyBatis 的依賴乍赫,當(dāng)然也少不了數(shù)據(jù)庫的依賴瓣蛀,這里我們?yōu)榱朔奖銓嶓w類的編寫我們還加上了 Lombok ,以及l(fā)og4j :

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.35</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.20</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

2.編寫配置文件

需要在類路徑下編寫配置文件:

<?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">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///spring_data"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
</configuration>

2.log4j配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration>

    <appender name="myConsole" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                   value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n" />
        </layout>
        <!--過濾器設(shè)置輸出的級別-->
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="levelMin" value="debug" />
            <param name="levelMax" value="warn" />
            <param name="AcceptOnMatch" value="true" />
        </filter>
    </appender>

    <appender name="myFile" class="org.apache.log4j.RollingFileAppender">
        <param name="File" value="D:/output.log" /><!-- 設(shè)置日志輸出文件名 -->
        <!-- 設(shè)置是否在重新啟動服務(wù)時雷厂,在原有日志的基礎(chǔ)添加新日志 -->
        <param name="Append" value="true" />
        <param name="MaxBackupIndex" value="10" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%p (%c:%L)- %m%n" />
        </layout>
    </appender>

    <appender name="activexAppender" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="E:/activex.log" />
        <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                   value="[%d{MMdd HH:mm:ss SSS\} %-5p] [%t] %c{3\} - %m%n" />
        </layout>
    </appender>

    <!-- 指定logger的設(shè)置惋增,additivity指示是否遵循缺省的繼承機制-->
    <logger name="com.runway.bssp.activeXdemo" additivity="false">
        <appender-ref ref="activexAppender" />
    </logger>

    <!-- 根logger的設(shè)置-->
    <root>
        <priority value ="debug"/>
        <appender-ref ref="myConsole"/>
        <appender-ref ref="myFile"/>
    </root>
</log4j:configuration>

3.編寫實體類

package lwen.entries;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Employee {
    private int id;
    private String name;
    private int age;
}

4.編寫測試類

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class GettingStart {
    @Test
    public void sessionFactoryTest() throws IOException {
        String resource = "mybatis.xml";
        InputStream stream = Resources.getResourceAsStream(resource);
        SqlSession sqlSession = null;
       try {
           //獲取sql工廠
           SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(stream);
           //獲取sql session
           sqlSession = sessionFactory.openSession();

           // 1.sql標(biāo)識 2.綁定的參數(shù)
           Object employee = sqlSession.selectOne("selectOneEmployee", 3);
           System.out.println(employee);
       }finally {
           if (sqlSession != null) {
               sqlSession.close();
           }
       }

    }
}

5.編寫mapper文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC " -//mybatis.org//DTD Mapper 3.e//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.mybatis.example.BlogMapper">
    <select id="selectOneEmployee" resultType="lwen.entries.Employee">
      select * from employee where id=#{id}
    </select>
</mapper>

注意這里其實我們的mapper和測試類里的參數(shù)必須是需要匹配的才行。比如我們的 id 就是我們的測試類中的 select 方法需要傳的參數(shù)改鲫,然后我們的 resultType 就是一個實體類的具體路徑诈皿。

6.總結(jié)基本套路

  1. 根據(jù)xml配置文件(全局配置文件)創(chuàng)建一個Sq1SessionFactory對象,xml是用來配置數(shù)據(jù)源一些運行環(huán)境信息

  2. sql映射文件:配置了每一個sql像棘,以及sql的封裝規(guī)則等稽亏。

  3. 將sq1映射文件注冊在全局配置文件中

  4. 寫Java代碼:

    1)、根據(jù)全局置文件得到Sq1SessionFactory缕题;
    2)截歉、使用sqlSession工廠,獲取到sqlSession對象使用他來執(zhí)行增改查烟零,一個sqlSession就是代表和數(shù)據(jù)庫的一次會話瘪松,用完關(guān)閉
    3)咸作、使用sql的唯一標(biāo)志來告訴MyBatis執(zhí)行哪個sql,語句都是保存在Sql映射文件中的宵睦。

上面我們使用的方式是以前比較老的方式记罚,現(xiàn)在不再使用那種方式了,我們現(xiàn)在都是面向的接口編程的壳嚎,所以我們使用Mapper 類來完成數(shù)據(jù)庫訪問桐智。

3.面向接口編程

1.編寫接口Mapper

創(chuàng)建一個mapper接口,然后里面寫方法即可:

package lwen.dao;

import lwen.entries.Employee;

public interface EmployeeMapper {
    public Employee getEmployeeById(Integer id);
}

可以看到就是這么簡單诬辈,但是我們一開始是通過方法的參數(shù)和我們的 xml 的查詢語句鏈接起來的酵使,這里我們又怎么做這個映射關(guān)系呢?其實就是需要在我們的 xml 中配置我們的 這個Mapper 的路徑焙糟,以及我們的方法作為查詢語句的 id 屬性口渔,還有返回值類型,等等穿撮。接下來就來看這些配置缺脉。

2.配置Mapper.xml

接下來就是配置我們的 mapper 的xml了,讓他和我們的接口掛鉤悦穿。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC " -//mybatis.org//DTD Mapper 3.e//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="lwen.dao.EmployeeMapper">
    <select id="getEmployeeById" resultType="lwen.entries.Employee">
      select * from employee where id=#{id}
    </select>
</mapper>

注意事項:

  1. 第一點就是我們的 namespace 以前事隨便寫攻礼,但是這個地方就是需要我們和Mapper 接口綁定,也就是我們的接口的全類名栗柒。
  2. 然后就是我們的id屬性礁扮,就是我們的Mapper的方法名。
  3. 還有一點疑問就是我們的參數(shù)瞬沦,我們都沒傳太伊,其實這里他做了默認綁定,參數(shù)名和這里的sql模板參數(shù)名一致就行逛钻。

3.測試類

@Test
public void InterfaceMapperTest() throws IOException {
    String resource = "mybatis.xml";
    InputStream stream = Resources.getResourceAsStream(resource);
    SqlSession sqlSession = null;
   try {
       //獲取sql工廠
       SqlSessionFactory sessionFactory = getSessionFactory("mybatis.xml");
       //獲取sql session
       sqlSession = sessionFactory.openSession();

       // 獲取 mapper 接口的實例對象
       EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
       //直接調(diào)用的 mapper 里的方法
       System.out.println(employeeMapper.getEmployeeById(3));

   }finally {
       if (sqlSession != null) {
           sqlSession.close();
       }
   }

}

4.一個神奇的點

這里我們會發(fā)現(xiàn)我們根本沒有寫接口的實現(xiàn)類僚焦,我們怎么獲取到我們的 Mapper 的對象,并且還可以調(diào)用他的方法呢曙痘?實際上我們?nèi)ゴ蛴∫幌挛覀兪褂?sqlSession.getMapper(EmployeeMapper.class) 這句話獲取到我們的對象芳悲,并且能執(zhí)行相應(yīng)的操作呢?

我們打印出來這個對象我們就會發(fā)現(xiàn)边坤,獲取到的對象實際上是一個代理對象名扛,那么也就是說我們 Mybatis 底層采用的代理方式做的具體的功能。

其實我們通過SqlSession.getMapper(XXXMapper.class) 方法茧痒,MyBatis 會根據(jù)相應(yīng)的接口聲明的方法信息肮韧,通過動態(tài)代理機制生成一個Mapper 實例,我們使用Mapper 接口的某一個方法時,MyBatis 會根據(jù)這個方法的方法名和參數(shù)類型惹苗,確定Statement Id,底層還是通過SqlSession.select("statementId",parameterObject);或者SqlSession.update("statementId",parameterObject); 等等來實現(xiàn)對數(shù)據(jù)庫的操作耸峭,(至于這里的動態(tài)機制是怎樣實現(xiàn)的桩蓉,我想專門用一篇文章來討論)

MyBatis 引用 Mapper 接口這種調(diào)用方式,純粹是為了滿足面向接口編程的需要劳闹。(其實還有一個原因是在于院究,面向接口的編程,使得用戶在接口上可以使用注解來配置SQL語句本涕,這樣就可以脫離XML配置文件业汰,實現(xiàn)“0配置”)。 因為面向接口編程其實有非常多的好處菩颖。因為現(xiàn)在我們的 dao 代碼就是我們的 mapper 接口了样漆,但是如果有一天我們希望不采用 MyBatis 來做數(shù)據(jù)訪問了,我們在底層就可以直接寫對應(yīng)的實現(xiàn)類使用 Hibernate 等等其他框架來頂替晦闰,也是一件很容易的事放祟。

4.總結(jié)

  1. SqlSession代表和數(shù)據(jù)庫的一次會話:用完必須關(guān)閉,這也是一個資源呻右,所以我們用完了必須進行關(guān)閉操作跪妥,避免數(shù)據(jù)庫不必要的問題。
  2. SqlSession和connection一樣都是非線程安全声滥,每次使用都應(yīng)該去獲取新的對象眉撵,不可以當(dāng)作一個成員變量 ,不然自然會導(dǎo)致紊亂落塑,也就是我們需要把他放在一個局部方法中纽疟,用完關(guān)閉。其實說清楚點他的底層就是 connection芜赌。
  3. mapper接口沒有實現(xiàn)類仰挣,但是mybatis會為這個接口生成一個代理對象。(將接口和xml進行綁定)
  4. 兩個重要的配置文件:
    1. mybatis的全局配置文件:包含數(shù)據(jù)庫連接池信息缠沈,事務(wù)管理器信息等膘壶。。洲愤。系統(tǒng)運行環(huán)境信息
    2. sql映射文件:保存了每一個sq1語句的映射信息:將sql抽取出來颓芭。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市柬赐,隨后出現(xiàn)的幾起案子亡问,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件州藕,死亡現(xiàn)場離奇詭異束世,居然都是意外死亡,警方通過查閱死者的電腦和手機床玻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門毁涉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锈死,你說我怎么就攤上這事贫堰。” “怎么了待牵?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵其屏,是天一觀的道長。 經(jīng)常有香客問我缨该,道長偎行,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任压彭,我火速辦了婚禮睦优,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘壮不。我一直安慰自己汗盘,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布询一。 她就那樣靜靜地躺著隐孽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪健蕊。 梳的紋絲不亂的頭發(fā)上菱阵,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音缩功,去河邊找鬼晴及。 笑死,一個胖子當(dāng)著我的面吹牛嫡锌,可吹牛的內(nèi)容都是我干的虑稼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼势木,長吁一口氣:“原來是場噩夢啊……” “哼蛛倦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起啦桌,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤溯壶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體且改,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡验烧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了又跛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片噪窘。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖效扫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情直砂,我是刑警寧澤菌仁,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站静暂,受9級特大地震影響济丘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜洽蛀,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一摹迷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧郊供,春花似錦峡碉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至疯淫,卻和暖如春地来,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背熙掺。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工未斑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人币绩。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓蜡秽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親类浪。 傳聞我的和親對象是個殘疾皇子载城,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容