Mybatis 關鍵組件(注意各組件的最佳做用域)

Mybatis

幾個使用時的重要組件

SqlSessionFactoryBuilder

這個類能夠被實例化、使用和丟棄,一旦建立了 SqlSessionFactory,就再也不須要它了。所以 SqlSessionFactoryBuilder 實例的最佳做用域是方法做用域(也就是局部方法變量)。你能夠重用 SqlSessionFactoryBuilder 來建立多個 SqlSessionFactory 實例,可是最好仍是不要讓其一直存在以保證全部的 XML 解析資源開放給更重要的事情。java

SqlSessionFactory

SqlSessionFactory 一旦被建立就應該在應用的運行期間一直存在,沒有任何理由對它進行清除或重建。使用 SqlSessionFactory 的最佳實踐是在應用運行期間不要重複建立屢次,屢次重建 SqlSessionFactory 被視爲一種代碼「壞味道(bad smell)」。所以 SqlSessionFactory 的最佳做用域是應用做用域。有不少方法能夠作到,最簡單的就是使用單例模式或者靜態單例模式。mysql

SqlSession

每一個線程都應該有它本身的 SqlSession 實例。SqlSession 的實例不是線程安全的,所以是不能被共享的,因此它的最佳的做用域是請求或方法做用域。絕對不能將 SqlSession 實例的引用放在一個類的靜態域,甚至一個類的實例變量也不行。也毫不能將 SqlSession 實例的引用放在任何類型的管理做用域中,好比 Servlet 架構中的 HttpSession。若是你如今正在使用一種 Web 框架,要考慮 SqlSession 放在一個和 HTTP 請求對象類似的做用域中。換句話說,每次收到的 HTTP 請求,就能夠打開一個 SqlSession,返回一個響應,就關閉它。這個關閉操做是很重要的,你應該把這個關閉操做放到 finally 塊中以確保每次都能執行關閉。下面的示例就是一個確保 SqlSession 關閉的標準模式:sql

SqlSession session = sqlSessionFactory.openSession();
try {
  // do work
} finally {
  session.close();
}

映射器實例(Mapper Instances)

映射器是一個你建立來綁定你映射的語句的接口。映射器接口的實例是從 SqlSession 中得到的。所以從技術層面講,任何映射器實例的最大做用域是和請求它們的 SqlSession 相同的。儘管如此,映射器實例的最佳做用域是方法做用域。也就是說,映射器實例應該在調用它們的方法中被請求,用過以後便可廢棄。並不須要顯式地關閉映射器實例,儘管在整個請求做用域(request scope)保持映射器實例也不會有什麼問題,可是很快你會發現,像 SqlSession 同樣,在這個做用域上管理太多的資源的話會難於控制。因此要保持簡單,最好把映射器放在方法做用域(method scope)內。下面的示例就展現了這個實踐:數據庫

SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  // do work
} finally {
  session.close();
}

配置文件

properties

這些屬性都是可外部配置且可動態替換的,既能夠在典型的 Java 屬性文件中配置,亦可經過 properties 元素的子元素來傳遞。例如:api

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>

若是屬性在不僅一個地方進行了配置,那麼 MyBatis 將按照下面的順序來加載:安全

  • 在 properties 元素體內指定的屬性首先被讀取。
  • 而後根據 properties 元素中的 resource 屬性讀取類路徑下屬性文件或根據 url 屬性指定的路徑讀取屬性文件,並覆蓋已讀取的同名屬性。
  • 最後讀取做爲方法參數傳遞的屬性,並覆蓋已讀取的同名屬性。

所以,經過方法參數傳遞的屬性具備最高優先級,resource/url 屬性中指定的配置文件次之,最低優先級的是 properties 屬性中指定的屬性。session

通過嘗試確實是這樣,若是resource配置文件裏的屬性會由於後讀取而覆蓋properties屬性裏指定的屬性!mybatis

而方法傳遞的properties優先級最高.看下面這個例子:架構

public static SqlSessionFactory getSqlSessionFactory(String resource) throws Exception {
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream, getProperties());
    }

    public static Properties getProperties() {
        String driver = "com.mysql.cj.jdbc.Driver";
        String username = "pinker";
        String password = "*****";
        String url = "jdbc:mysql://localhost:3306/cmb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC";
        Properties properties = new Properties();
        properties.put("driver", driver);
        properties.put("username", username);
        properties.put("password", password);
        properties.put("url", url);
        return properties;
    }

其實上面代碼裏的inputstream讀取的配置文件裏就有很全的配置屬性,可是能夠發現,這裏咱們動態地覆蓋了它,這樣是否是能夠動態地切換數據庫了,哈哈!app

固然還有更後面的參數注入方法,而且覆蓋我上面說的這個api-public SqlSessionFactory build(InputStream inputStream, Properties properties)

下面咱們主要用到的api是:SqlSession openSession(Connection var1);

public void setUp() throws Exception {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(resource);
        String username = "pinker";
        String password = "*****";
        String url = "jdbc:mysql://localhost:3306/cmb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC";
        Connection connection = DriverManager.getConnection(url, username, password);
        session = sqlSessionFactory.openSession(connection);
        repo = session.getMapper(MonitorRepo.class);
    }

正如咱們所說,這個connection會覆蓋上面所說的屬性值.

typeAliases

有兩種映射:

  • 每一個類單獨映射(不經常使用)
  • 整個包映射(經常使用!)

搭配@Alias註解每個在指定包中的 Java Bean,在沒有註解的狀況下,會使用 Bean 的首字母小寫的非限定類名來做爲它的別名。

下面表格是一些爲常見的 Java 類型內建的相應的類型別名。它們都是大小寫不敏感的,須要注意的是由基本類型名稱重複致使的特殊處理。(能夠發現咱們不須要改變習慣!這個很棒!)

別名 映射的類型
_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
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator

註解

public interface AnotationRepo {

    @Select("select * from monitor")
    @Results(value = {
            @Result(property = "userName", column = "user_name"),
            @Result(column = "did", property = "dbId"),
            @Result(column = "pages_sec", property = "pagesPerSeconds"),
            @Result(column = "ava_bytes", property = "avaliableBytes"),
            @Result(column = "buffer_cache_ratio", property = "bufferCacheRatio"),
            @Result(column = "current_connections", property = "connectionsNums"),
            @Result(column = "cpu_ratio", property = "cpuRatio"),
            @Result(column = "disk_ratio", property = "diskRation")
    })
    public List<MonitorInfo> queryInfo();

    @UpdateProvider(type = MySQLProvider.class, method = "updateList")
    public int updateMonitorInfo(MonitorInfo info);
}

ISSUE

  1. 錯誤: org.xml.sax.SAXParseException; lineNumber: 34; columnNumber: 17; 元素類型爲 "configuration" 的內容必須匹配 。或者再配置文件裏IDEA會顯示錯誤

    緣由:在配置mybatis-config.xml時,其中的節點是有順序的,配置順序依次爲:

    properties/settings/typeAliases/typeHandlers/objectFactory/objectWrapperFactory/plugins/environments/databaseIdProvider/mappers

相關文章
相關標籤/搜索