Mybatis 关键组件(注意各组件的最佳作用域)
2019獨角獸企業重金招聘Python工程師標準>>>
Mybatis
幾個使用時的重要組件
SqlSessionFactoryBuilder
這個類可以被實例化、使用和丟棄,一旦創建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 實例的最佳作用域是方法作用域(也就是局部方法變量)。你可以重用 SqlSessionFactoryBuilder 來創建多個 SqlSessionFactory 實例,但是最好還是不要讓其一直存在以保證所有的 XML 解析資源開放給更重要的事情。
SqlSessionFactory
SqlSessionFactory 一旦被創建就應該在應用的運行期間一直存在,沒有任何理由對它進行清除或重建。使用 SqlSessionFactory 的最佳實踐是在應用運行期間不要重復創建多次,多次重建 SqlSessionFactory 被視為一種代碼“壞味道(bad smell)”。因此 SqlSessionFactory 的最佳作用域是應用作用域。有很多方法可以做到,最簡單的就是使用單例模式或者靜態單例模式。
SqlSession
每個線程都應該有它自己的 SqlSession 實例。SqlSession 的實例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。絕對不能將 SqlSession 實例的引用放在一個類的靜態域,甚至一個類的實例變量也不行。也絕不能將 SqlSession 實例的引用放在任何類型的管理作用域中,比如 Servlet 架構中的 HttpSession。如果你現在正在使用一種 Web 框架,要考慮 SqlSession 放在一個和 HTTP 請求對象相似的作用域中。換句話說,每次收到的 HTTP 請求,就可以打開一個 SqlSession,返回一個響應,就關閉它。這個關閉操作是很重要的,你應該把這個關閉操作放到 finally 塊中以確保每次都能執行關閉。下面的示例就是一個確保 SqlSession 關閉的標準模式:
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 元素的子元素來傳遞。例如:
<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 屬性中指定的屬性。
經過嘗試確實是這樣,如果resource配置文件里的屬性會因為后讀取而覆蓋properties屬性里指定的屬性!
而方法傳遞的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讀取的配置文件里就有很全的配置屬性,但是可以發現,這里我們動態地覆蓋了它,這樣是不是可以動態地切換數據庫了,哈哈!
當然還有更后面的參數注入方法,并且覆蓋我上面說的這個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
錯誤: org.xml.sax.SAXParseException; lineNumber: 34; columnNumber: 17; 元素類型為 "configuration" 的內容必須匹配 。或者再配置文件里IDEA會顯示錯誤
原因:在配置mybatis-config.xml時,其中的節點是有順序的,配置順序依次為:
properties/settings/typeAliases/typeHandlers/objectFactory/objectWrapperFactory/plugins/environments/databaseIdProvider/mappers
轉載于:https://my.oschina.net/xd03122049/blog/1861083
總結
以上是生活随笔為你收集整理的Mybatis 关键组件(注意各组件的最佳作用域)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Iterator:访问数据集合的统一接口
- 下一篇: React Native升级目标SDK