Java框架之MyBatis框架(一)

1、框架介紹:java

  MyBatis是一個優秀的持久層框架,它對jdbc的操做數據庫的過程進行封裝,使開發者只須要關注 SQL 自己,而不須要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。mysql

  Mybatis經過xml或註解的方式將要執行的各類statement(statement、preparedStatemnt、CallableStatement---java中調存儲過程)配置起來,並經過java對象和statement中的sql進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射成java對象並返回。程序員

2、對比下,JDBC存在的問題:spring

一、  數據庫鏈接建立、釋放頻繁形成系統資源浪費,從而影響系統性能。若是使用數據庫鏈接池可解決此問題。sql

二、  Sql語句在代碼中硬編碼,形成代碼不易維護,實際應用中sql變化的可能較大,sql變更須要改變java代碼。數據庫

三、  使用preparedStatement向佔位符號傳參數存在硬編碼,由於sql語句的where條件不必定,可能多也可能少,修改sql還要修改代碼,系統不易維護。apache

四、對結果集解析存在硬編碼(查詢列名),sql變化致使解析代碼變化,系統不易維護,若是能將數據庫記錄封裝成pojo對象解析比較方便。編程

3、架構:緩存

一、  mybatis配置安全

SqlMapConfig.xml,此文件做爲mybatis的全局配置文件,配置了mybatis的運行環境等信息。------一個表對應一個XML!!

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編程中對結果的解析處理過程。

4、配置:

一、加入mybatis核心包、依賴包、數據驅動包:

 

二、建立:

建立資源文件夾(source Folder是個資源文件夾:資源文件夾被引用是不須要加文件名,是默認的根目錄的!)config,加入log4j.properties和SqlMapConfig.xml配置文件

log4j.properties:

        mybatis默認使用log4j做爲輸出日誌信息。

# 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:(已進行最後的配置修改)

<?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是屬性-這個地址(source file類型的)是資源文件夾,不須要寫src ,-->
    <properties resource="db.properties"></properties>
    
    
    <!-- 配置別名 不區分大小寫-->
     <typeAliases>
        <!--<typeAlias alias="user" type="com.oracle.pojo.User"/>-->
        <!-- 將pojo裏的全部類配置別名 -->
        <package name="com.oracle.pojo"/>
    </typeAliases> 
    
    
    <!--environments 環境集合屬性對象:單獨使用此框架的時候使用, 和spring整合後 environments配置將廢除 -->
    <environments default="development">
              <!-- environment環境子屬性對象 --> <environment id="development"> <!-- transactionManager:事務管理-使用jdbc事務管理 --> <transactionManager type="JDBC" /> <!-- dataSource:數據源-數據庫鏈接池 --> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <!-- mappers映射器 必須掌握--> <mappers> <!-- <mapper resource="com/oracle/mapper/UserMapper.xml"/> 原來的寫法 <mapper class="com.oracle.mapper.UserMapper"/> 使用mapper接口類路徑。。。下面是註冊指定包下的全部mapper接口 --> <package name="com.oracle.mapper"/> </mappers> </configuration>

 建立pojo類:

package com.oracle.pojo;

public class Orders {
    private Integer id;
    private Integer userId;
    private String number;
    private String createtime;
    private String note;
    private User user;//一對一的話直接私有個類,一對多就得List<User>
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }
    public String getCreatetime() {
        return createtime;
    }
    public void setCreatetime(String createtime) {
        this.createtime = createtime;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    @Override
    public String toString() {
        return "Orders [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime
                + ", note=" + note + ", user=" + user + "]";
    }
    
    
    
}

在config下的sqlmap目錄下建立sql映射文件User.xml:

<?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 -->
<mapper namespace="com.oracle.mapper.OrdersMapper">
    <resultMap type="orders" id="getOrders">
        <!-- <id property="id" column="id"/> -->
        <result property="userId" column="user_id"/>
    </resultMap>
<!--查詢全部訂單信息  -->

<!-- id:statement的id 或者叫作sql的id-->

    <!-- parameterType:聲明輸入參數的類型 -->

    <!-- resultType:聲明輸出結果的類型,應該填寫pojo的全路徑 -->

    <!-- #{}:輸入參數的佔位符,至關於jdbc的? -->

<select id="getAllOrders" resultMap="getOrders">
    select * from orders
</select>
    <!--查詢全部的訂單信息以及其關聯的用戶信息  -->
        <!-- 由於兩個表是一對一!爲使用resultMap,因此在orders下添加私有的User類對應的user屬性,由於沒法將數據映射到user裏面
        因此開始下面的手動映射 -->
    <resultMap type="orders" id="orderUserResultMap">
    <id property="id" column="id" />
    <result property="userId" column="user_id" />
    <result property="number" column="number" />
    <result property="createtime" column="createtime" />
    <result property="note" column="note" />

    <!-- association :配置一對一屬性 -->
    <!-- property:order裏面的User屬性名 -->
    <!-- javaType:屬性類型 -->
    <association property="user" javaType="user">
        <!-- id:聲明主鍵,表示user_id是關聯查詢對象的惟一標識-->
        <id property="id" column="user_id" />
        <result property="username" column="username" />
        <result property="address" column="address" />
    </association>

</resultMap>

<!-- 一對一關聯,查詢訂單,訂單內部包含用戶屬性 -->
<select id="getOrdersUser" resultMap="orderUserResultMap">
    SELECT
    o.id,
    o.user_id userId,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
    FROM
    `orders` o
    LEFT JOIN `user` u ON o.user_id = u.id
</select>
</mapper>

mybatis框架須要加載Mapper.xml映射文件,將users.xml添加在SqlMapConfig.xml:(上圖已添加)

 

測試下:

    // 查詢全部的訂單及用戶信息
    public static void method02() throws IOException {
        // 1. 建立SqlSessionFactoryBuilder對象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 2. 加載SqlMapConfig.xml配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 建立SqlSessionFactory對象
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        // 4. 建立SqlSession對象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 5.執行sql
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);// 得到一個(動態代理)UserMapper接口的實現類對象
        List<Orders> list = ordersMapper.getOrdersUser();
        System.out.println(list);
        // 6.釋放資源
        sqlSession.close();
    }

5、小結:

  #{}表示一個佔位符號?,經過#{}能夠實現preparedStatement向佔位符中設置值,自動進行java類型和jdbc類型轉換。#{}能夠有效防止sql注入。 #{}能夠接收簡單類型值或pojo屬性值。 若是parameterType傳輸單個簡單類型值,#{}括號中能夠是value或其它名稱。

 

  ${}表示拼接sql串(拼串就能引發注入),經過${}能夠將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換, ${}能夠接收簡單類型值或pojo屬性值,若是parameterType傳輸單個簡單類型值,${}括號中只能是value。

 

  parameterType:指定輸入參數類型,mybatis經過ognl從輸入對象中獲取參數值拼接在sql中。

  resultType:指定輸出結果類型,mybatis將sql查詢結果的一行記錄數據映射爲resultType指定類型的對象。若是有多條數據,則分別進行映射,並把對象放到容器List中(寫泛型)

6、Mybatis解決jdbc編程的問題:

一、  數據庫鏈接建立、釋放頻繁形成系統資源浪費從而影響系統性能,若是使用數據庫鏈接池可解決此問題。

解決:在SqlMapConfig.xml中配置數據鏈接池,使用鏈接池管理數據庫連接。

二、  Sql語句寫在代碼中形成代碼不易維護,實際應用sql變化的可能較大,sql變更須要改變java代碼。

解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。

三、  向sql語句傳參數麻煩,由於sql語句的where條件不必定,可能多也可能少,佔位符須要和參數一一對應。

解決:Mybatis自動將java對象映射至sql語句,經過statement中的parameterType定義輸入參數的類型。

四、  對結果集解析麻煩,sql變化致使解析代碼變化,且解析前須要遍歷,若是能將數據庫記錄封裝成pojo對象解析比較方便。

解決:Mybatis自動將sql執行結果映射至java對象,經過statement中的resultType定義輸出結果的類型。

7、mybatis與hibernate不一樣

  Mybatis和hibernate不一樣,它不徹底是一個ORM框架,由於MyBatis須要程序員本身編寫Sql語句。mybatis能夠經過XML或註解方式靈活配置要運行的sql語句,並將java對象和sql語句映射生成最終執行的sql,最後將sql執行的結果再映射生成java對象。

 

  Mybatis學習門檻低,簡單易學,程序員直接編寫原生態sql,可嚴格控制sql執行性能,靈活度高,很是適合對關係數據模型要求不高的軟件開發,例如互聯網軟件、企業運營類軟件等,由於這類軟件需求變化頻繁,一但需求變化要求成果輸出迅速。可是靈活的前提是mybatis沒法作到數據庫無關性,若是須要實現支持多種數據庫的軟件則須要自定義多套sql映射文件,工做量大。

 

  Hibernate對象/關係映射能力強,數據庫無關性好,對於關係模型要求高的軟件(例如需求固定的定製化軟件)若是用hibernate開發能夠節省不少代碼,提升效率。可是Hibernate的學習門檻高,要精通門檻更高,並且怎麼設計O/R映射,在性能和對象模型之間如何權衡,以及怎樣用好Hibernate須要具備很強的經驗和能力才行。

  總之,按照用戶的需求在有限的資源環境下只要能作出維護性、擴展性良好的軟件架構都是好架構,因此框架只有適合纔是最好。 

8、Dao開發方法:      

        原始Dao開發方法和Mapper動態代理開發方法。

(一)、sqlsession:

一、SqlSession中封裝了對數據庫的操做,如:查詢、插入、更新、刪除等。

SqlSession經過SqlSessionFactory建立。

SqlSessionFactory是經過SqlSessionFactoryBuilder進行建立。

二、SqlSessionFactoryBuilder用於建立SqlSessionFacoty,SqlSessionFacoty一旦建立完成就不須要SqlSessionFactoryBuilder了,由於SqlSession是經過SqlSessionFactory建立的。因此能夠將SqlSessionFactoryBuilder當成一個工具類使用,最佳使用範圍是方法範圍即方法體內局部變量。

三、SqlSessionFactory是一個接口,接口中定義了openSession的不一樣重載方法,SqlSessionFactory的最佳使用範圍是整個應用運行期間,一旦建立後能夠重複使用,一般以單例模式管理SqlSessionFactory。

四、SqlSession是一個面向用戶的接口,sqlSession中定義了數據庫操做方法。

        每一個線程都應該有它本身的SqlSession實例。SqlSession的實例不能共享使用,它也是線程不安全的。所以最佳的範圍是請求或方法範圍。絕對不能將SqlSession實例的引用放在一個類的靜態字段或實例字段中。

(二)、原始Dao開發方法須要程序員編寫Dao接口和Dao實現類。

原始Dao開發中存在如下問題:

一、 Dao方法體存在重複代碼:經過SqlSessionFactory建立SqlSession,調用SqlSession的數據庫操做方法

二、 調用sqlSession的數據庫操做方法須要指定statement的id,這裏存在硬編碼,不便於開發維護。

(三)、Mapper:動態代理!!!

  Mapper接口開發方法只須要程序員編寫Mapper接口(至關於Dao接口),由Mybatis框架根據接口定義建立接口的動態代理對象(一個接口的實現類對象),代理對象的方法體同上邊Dao接口實現類方法。

 

  Mapper接口開發須要遵循如下規範:

一、  Mapper.xml文件中的namespace與mapper接口的類路徑相同。

二、  Mapper接口方法名和Mapper.xml中定義的每一個statement的id相同

三、  Mapper接口方法的輸入參數類型和mapper.xml中定義的每一個sql 的parameterType的類型相同

四、  Mapper接口方法的輸出參數類型和mapper.xml中定義的每一個sql的resultType的類型相同

package com.oracle.mapper;

import java.util.List;

import com.oracle.pojo.Query;
import com.oracle.pojo.QueryVo;
import com.oracle.pojo.User;

public interface UserMapper {
//    Mapper接口開發須要遵循如下規範:
    //一、    Mapper.xml文件中的namespace與mapper接口的類路徑相同。
    //二、    Mapper接口方法名和Mapper.xml中定義的每一個statement的id相同 
    //三、    Mapper接口方法的輸入參數類型和mapper.xml中定義的每一個sql 的parameterType的類型相同
    //四、    Mapper接口方法的輸出參數類型和mapper.xml中定義的每一個sql的resultType的類型相同
    //一個新的--建立一個xml文件和接口!xml裏面配置接口的地址(包+類)<mapper namespace="com.oracle.mapper.UserMapper">
    //    根據id查詢User
    public  User getUserById(Integer id);
    //根據用戶名模糊查詢用戶列表
    public List<User> getUserByUserName(String username);
    //新增用戶
    public void addUser(User user);
    //刪除用戶
    public void deleteUser(Integer id);
    //修改用戶
    public void updateUser(User user);
    //根據QueryVo的模糊查詢用戶列表
    public List<User> getUsernameByQueryVo(QueryVo vo);
    //查詢總記錄數
    public Integer getCount();
    //根據姓名和性別查明用戶
    public List<User> getUserBySexAndUserName(User user);
    //根據多個id查詢用戶
    public List<User> getUserByQuery(Query query);
    //查詢全部用戶信息及訂單信息
    public List<User> getUserOrders();
}

一、定義mapper映射文件UserMapper.xml,將UserMapper.xml放在config下mapper目錄下;

二、建立UserMapper接口

三、修改SqlMapConfig.xml文件加載UserMapper.xml

注: namespace

  mybatis官方推薦使用mapper代理方法開發mapper接口,程序員不用編寫mapper接口實現類,使用mapper代理方法時,輸入參數可使用pojo包裝對象或map對象,保證dao的通用性。

9、SqlMapConfig.xml配置文件

(一)、SqlMapConfig.xml中配置的內容和順序以下:

 

properties(屬性)

settings(全局配置參數)

typeAliases(類型別名)

typeHandlers(類型處理器)

objectFactory(對象工廠)

plugins(插件)

environments(環境集合屬性對象)

environment(環境子屬性對象)

transactionManager(事務管理)

dataSource(數據源)

mappers(映射器)

(二)、SqlMapConfig.xml能夠引用java屬性文件中的配置信息以下:

 

在config下定義db.properties(屬性)file文件:鍵值對形式,都必須是String類型!

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

 

MyBatis 將按照下面的順序來加載屬性:

一、 在 properties 元素體內定義的屬性首先被讀取。

二、 而後會讀取properties 元素中resource或 url 加載的屬性,它會覆蓋已讀取的同名屬性。

(三)、typeAliases(類型別名)---也能夠起別名

別名

映射的類型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

map

Map

(四)、mappers映射器:

一、使用相對於類路徑的資源:

如:<mapper resource="sqlmap/User.xml" />

二、使用mapper接口類路徑

如:<mapper class="cn.mybatis.mapper.UserMapper"/>

 

注意:此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中。

三、註冊指定包下的全部mapper接口

如:<package name="cn.mybatis.mapper"/>

最後:目錄:

相關文章
相關標籤/搜索