SSM框架系列-從JDBC到Mybatis(一)

前言

Java學(xué)到一定程度涩惑,框架終歸是不可避免的奉呛,畢竟程序開發(fā)很多時候不是一個人的事兒畔勤。這兩天學(xué)習(xí)了MyBatis框架胯陋,想著結(jié)合一下這幾天學(xué)到的東西和實習(xí)的經(jīng)驗總結(jié)一下蕊温。大概的思路就是從JDBC的缺陷到MyBatis的介紹和運行流程,再就是Mybatis的一個增刪改查小程序遏乔;然后是企業(yè)中MyBatis進(jìn)行數(shù)據(jù)庫開發(fā)時采用Dao方法和Mapper方法的一個介紹寿弱,最后是和Spring的一個整合。

也希望大家提出寶貴的建議按灶。

JDBC

JDBC小程序

DBHelper(數(shù)據(jù)庫連接類)

/**
  * @param連接數(shù)據(jù)庫
  * */
public class DBHelper {
    //參數(shù)配置
//public static final String url = "jdbc:mysql://127.0.0.1/test";
public static final String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf-8";
public static final String name = "com.mysql.jdbc.Driver";
public static final String user = "root";
public static final String password = "8888";

public static Connection conn= null;

public DBHelper() {
    // TODO Auto-generated constructor stub
    try{
        Class.forName(name);            //加載數(shù)據(jù)庫驅(qū)動
        conn = DriverManager.getConnection(url, user, password);    //通過驅(qū)動管理類獲取數(shù)據(jù)庫鏈接
    }catch(Exception e){
        e.printStackTrace();
    }
}

public static void Close(){
    try {
        conn.close();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}   
}

testJdbc(測試SQL查詢)

public class testJdbc {

private static String sql = null;
private static DBHelper db = null;

public static PreparedStatement pst = null;
public static ResultSet ret = null;

public static void main(String[] args) {
    // TODO Auto-generated method stub
    db = new DBHelper();        //通過構(gòu)造器連接到數(shù)據(jù)庫
    System.out.println(db.conn);
    db.Close();
    /*
    //sql = "INSERT INTO `test`.`user` (`Username`, `Password`, `Age`, `Address`, `UserId`) VALUES"
    //      + " ('bb', '1234', '23', 'hubei', '4');";       //插入語句
    //sql = "UPDATE `test`.`user` SET `Username`='ouou' WHERE `UserId`='1';";   //更新語句
    sql = "DELETE * where `UserId` = '2'";                                  //刪除語句  
    String sql1 = "select * from user";                                     //選擇語句
    try {
        pst = db.conn.prepareStatement(sql);
        pst.execute();
        ret = pst.executeQuery(sql1);
        while(ret.next()){
            String name = ret.getString(1);
            String pass = ret.getString(2);
            String age = ret.getString(3);
            String addr = ret.getString(4);
            String id = ret.getString(5);
            System.out.println(id+" "+name+" "+pass+" "+age+" "+addr);
        }
    }catch(SQLException e){
        e.printStackTrace();
    }*/ 
  }
 }

問題總結(jié)

總結(jié)網(wǎng)上搜集到東西和自己實際遇到的歸納為以下幾點:

  • 數(shù)據(jù)庫頻繁地連接開啟和關(guān)閉症革,造成資源的浪費。(使用數(shù)據(jù)庫連接池進(jìn)行管理)
  • SQL語句鸯旁、preparedStatement設(shè)置參數(shù)硬編碼在Java代碼中噪矛,不利于系統(tǒng)維護(hù)量蕊。(使用xml進(jìn)行配置)
  • resultSet遍歷結(jié)果集數(shù)據(jù)時,也存在硬編碼艇挨。(將查詢的結(jié)果集残炮,自動映射成Java對象)

MyBatis

為什么選擇MyBatis

  MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優(yōu)秀的持久層框架缩滨。MyBatis 避免了幾乎所有的 JDBC 
代碼和手工設(shè)置參數(shù)以及抽取結(jié)果集势就。MyBatis 使用簡單的 XML 或注解來配置和映射基本體,將接口和 Java的 
POJOs(Plain Old Java Objects,普通的 Java對象)映射成數(shù)據(jù)庫中的記錄脉漏。(選自官網(wǎng))
  • 也就是說開發(fā)者只需要關(guān)注SQL本身苞冯,而不需要花費精力去處理例如注冊驅(qū)動、創(chuàng)建connection侧巨、創(chuàng)建statement舅锄、手動設(shè)置參數(shù)、結(jié)果集檢索等jdbc的過程代碼司忱。MyBatis通過xml或注解的方式將要執(zhí)行的各種statement(statement皇忿,preparedStatement、CallableStatement)配置起來坦仍,并通過Java對象和statement中的SQL進(jìn)行映射生成最終執(zhí)行的SQL語句鳍烁,最后又mybatis框架執(zhí)行SQL并將結(jié)果映射成Java對象并返回。

MyBatis是什么

MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code繁扎,并且改名為MyBatis老翘,實質(zhì)上Mybatis對ibatis進(jìn)行一些改進(jìn)。

MyBatis框架圖

Paste_Image.png

MyBatis的運行流程

  • 在SQLMapConfig.xml(mybati的全局配置文件)中配置mybatis的運行環(huán)境等信息锻离。并在其中加載mapper.xml(sql映射文件铺峭,配置了操作數(shù)據(jù)庫的SQL語句)文件。
  • 通過mybatis環(huán)境等配置信息構(gòu)造SQLSessionFactory會話工廠汽纠。
  • 由會話工廠創(chuàng)建SQLSession來操作數(shù)據(jù)庫卫键。
  • mybatis底層自定義了Executor執(zhí)行器接口操作數(shù)據(jù)庫,Executor接口有基本執(zhí)行器和緩存執(zhí)行器兩個實現(xiàn)虱朵。
  • Mapped Statement也是mybatis一個底層封裝對象莉炉,包裝了mybatis配置信息及SQL映射信息等。mapper.xml文件中一個SQL對應(yīng)一個Mapped Statement 對象碴犬,SQL的id即是Mapped Statement的id絮宁。
  • Mapped Statement對SQL執(zhí)行輸入?yún)?shù)進(jìn)行定義,包括HashMap服协、基本類型绍昂、pojo,Executor通過Mapped Statement在執(zhí)行SQL前將輸入的Java對象映射至SQL中,輸入?yún)?shù)映射就是jdbc編程中對preparedStatement設(shè)置參數(shù)窘游。
  • Mapped Statement對SQL執(zhí)行輸出結(jié)果進(jìn)行定義唠椭,包括HashMap、基本類型忍饰、pojo,Executor通過Mapped Statement在執(zhí)行SQL后將輸出結(jié)果映射至Java對象中贪嫂,輸出結(jié)果映射過程相當(dāng)于jdbc編程中結(jié)果的解析處理過程。

MyBatis的優(yōu)缺點及Hibernate的簡短比較

Mybatis和hibernate的不同之處在于它不是一個完全的ORM框架艾蓝,它需要開發(fā)者自己編寫SQL語句力崇,不過mybatis可以通過xml或注解方式靈活配置要運行的SQL語句,并將Java對象和SQL語句映射生成最終執(zhí)行的SQL赢织,最后將SQL執(zhí)行的結(jié)果再映射生成Java對象亮靴。
MyBatis相對于hibernate來說,學(xué)習(xí)門檻低敌厘,易于學(xué)習(xí),靈活度也高朽合,適合對關(guān)系數(shù)據(jù)模型要求不高的軟件開發(fā)俱两,以為其需求變化頻繁。正是因為mybatis的高度靈活曹步,所以它無法做到數(shù)據(jù)庫無關(guān)性宪彩,需要實現(xiàn)支持多種數(shù)據(jù)庫的軟件則需要自定義多套SQL映射文件。
Hibernate對象/關(guān)系映射能力強(qiáng)讲婚,數(shù)據(jù)庫無關(guān)性好尿孔,對于關(guān)系模型要求高的軟件(例如需求固定的定制化軟件)如果用hibernate開發(fā)可以節(jié)省很多代碼,提高效率筹麸。但是Hibernate的學(xué)習(xí)門檻高活合,要精通門檻更高,而且怎么設(shè)計O/R映射物赶,在性能和對象模型之間如何權(quán)衡白指,以及怎樣用好Hibernate需要具有很強(qiáng)的經(jīng)驗和能力才行。
所以如是說:沒有最好的框架酵紫,只有最適合的框架告嘲。

簡單的CRUD入門程序

導(dǎo)入的包:


Paste_Image.png

項目工程結(jié)構(gòu):


Paste_Image.png

輸出日志信息配置(log4j.properties):
# Global logging configuration
log4j.rootLogger = DEBUG,stdout
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):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 加載屬性文件 -->
<properties resource="db.properties">
</properties>
<!-- 和spring整合后 environments配置將廢除  -->
<environments default="development">
    <environment id="development">
    <!-- 使用jdbc事務(wù)管理 -->
        <transactionManager type="JDBC" />
    <!-- 數(shù)據(jù)庫連接池-->
        <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>
<!-- 加載映射文件 -->

<mappers>
    <mapper resource = "sqlmap/User.xml"/>
</mappers>

</configuration>

數(shù)據(jù)庫配置文件(db.properties)

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8
jdbc.username=root
jdbc.password=8888

User po類:

package com.howie.po;

import java.io.Serializable;
import java.util.Date;

/**
 * @param User po類
 */
public class User implements Serializable {

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

public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getUsername() {
    return username;
}
public void setUsername(String username) {
    this.username = username;
}
public String getSex() {
    return sex;
}
public void setSex(String sex) {
    this.sex = sex;
}
public Date getBirthday() {
    return birthday;
}
public void setBirthday(Date birthday) {
    this.birthday = birthday;
}
public String getAddress() {
    return address;
}
public void setAddress(String address) {
    this.address = address;
}
}

映射文件user.xml

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

<!-- 對SQL進(jìn)行分類話管理,理解SQL隔離
注意:是用mapper代理方法開發(fā)奖地,namespace有特殊重要的作用
 -->
<mapper namespace = "test">

<!-- 在映射文件中配置很多SQL語句 -->

<!-- 查找 -->
<select id = "findUserById" parameterType="int" resultType="com.howie.po.User">
    SELECT * FROM test.user where id = #{value}
</select>

<!-- 添加用戶 -->
<insert id="insertUser" parameterType="com.howie.po.User">
<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="deleteUserById" parameterType="int">
    delete from user where id=#{id}
</delete>

<!-- 更新用戶 -->
<update id="updateUser" parameterType="com.howie.po.User">
    update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
    where id=#{id}
</update>

</mapper>

測試文件MybatisTest類
(避免麻煩橄唬,測試一個查找語句,讀者感興趣的可以自行實現(xiàn)其他功能)

package com.howie.test;

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

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 com.howie.po.User;

public class MybatisTest {

public static void findUserByIdTest() throws IOException{
    //配置文件
    String resource = "SqlMapConfig.xml";
    
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //創(chuàng)建回話工廠
    SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(inputStream);
    //通過工廠得到SQLSession
    SqlSession ss = sf.openSession();
    //通過SQLSession操作數(shù)據(jù)庫
    //第一個參數(shù):映射文件中statement的id参歹,等于=namespace+statement的id
    //第二個參數(shù):制定和映射文件中所匹配的parameterType得參數(shù)
    //ss.selectOne結(jié)果是與映射文件中所匹配的resultType類型的對象
    User user = ss.selectOne("test.findUserById", 1);
    System.out.println(user);
    System.out.print(user.getAddress()+" "+user.getId()+" "+user.getUsername()+
            " "+user.getSex());
    System.out.println();
    //釋放資源
    ss.close();
}


  public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
        findUserByIdTest();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

未完待續(xù).......

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仰楚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缸血,老刑警劉巖蜜氨,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異捎泻,居然都是意外死亡飒炎,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門笆豁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來郎汪,“玉大人,你說我怎么就攤上這事闯狱∩酚” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵哄孤,是天一觀的道長照筑。 經(jīng)常有香客問我,道長瘦陈,這世上最難降的妖魔是什么凝危? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮晨逝,結(jié)果婚禮上蛾默,老公的妹妹穿的比我還像新娘。我一直安慰自己捉貌,他們只是感情好支鸡,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著趁窃,像睡著了一般牧挣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上醒陆,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天浸踩,我揣著相機(jī)與錄音,去河邊找鬼统求。 笑死检碗,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的码邻。 我是一名探鬼主播折剃,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼像屋!你這毒婦竟也來了怕犁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奏甫,沒想到半個月后戈轿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡阵子,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年思杯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挠进。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡色乾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出领突,到底是詐尸還是另有隱情暖璧,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布君旦,位于F島的核電站澎办,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏金砍。R本人自食惡果不足惜局蚀,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捞魁。 院中可真熱鬧至会,春花似錦离咐、人聲如沸谱俭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昆著。三九已至,卻和暖如春术陶,著一層夾襖步出監(jiān)牢的瞬間凑懂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工梧宫, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留接谨,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓塘匣,卻偏偏與公主長得像脓豪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子忌卤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

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

  • 1. 簡介 1.1 什么是 MyBatis 扫夜? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,527評論 0 4
  • 1 引言# 本文主要講解JDBC怎么演變到Mybatis的漸變過程,重點講解了為什么要將JDBC封裝成Mybait...
    七寸知架構(gòu)閱讀 76,497評論 36 980
  • Java數(shù)據(jù)持久化之mybatis 一. mybatis簡介 1.1 原始的JDBC操作: Java 通過 Jav...
    小Q逛逛閱讀 4,929評論 0 16
  • 自古清明行客少笤闯,吹笛只有牧牛郎堕阔。 添香何必非紅袖,一曲離殤夢也長颗味。 注:新韻
    幽小窗閱讀 429評論 101 41
  • #玩卡不卡·每日一抽# 每一位都可以通過這張卡片覺察自己: 1超陆、直覺他叫什么名字?鐵蛋 2脱衙、他幾歲了侥猬?8 3、他現(xiàn)...
    sui想閱讀 161評論 0 0