一、MyBatis簡介
- MyBatis 是一款優(yōu)秀的持久層框架,它支持自定義 SQL、存儲過程以及高級映射。
- MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。
- MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對象)為數(shù)據(jù)庫中的記錄。
- MyBatis特點(diǎn):簡單易學(xué);靈活;Sql和程序解耦;提供映射標(biāo)簽;提供關(guān)系映射標(biāo)簽;支持動態(tài)sql。
- MyBatis官網(wǎng):https://mybatis.org/mybatis-3/zh/getting-started.html
- MyBatis 本是apache的一個開源項(xiàng)目iBatis, 2010年這個項(xiàng)目由apache software foundation 遷移到了google code,并且改名為MyBatis 。2013年11月遷移到Github。 iBATIS一詞來源于“internet”和“abatis”的組合,是一個基于Java的持久層框架。
- MyBatis 支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC代碼和手 動設(shè)置參數(shù)以及獲取結(jié)果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生信息,將 接口和 Java的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數(shù)據(jù)庫中的記錄。
二、MyBatis配置與測試
XML 配置文件中包含了對 MyBatis 系統(tǒng)的核心設(shè)置,包括獲取數(shù)據(jù)庫連接實(shí)例的數(shù)據(jù)源(DataSource)以及決定事務(wù)作用域和控制方式的事務(wù)管理器(TransactionManager)。
每個基于 MyBatis 的應(yīng)用都是以一個 SqlSessionFactory 的實(shí)例為核心的。SqlSessionFactory 的實(shí)例可以通過 SqlSessionFactoryBuilder 獲得。而 SqlSessionFactoryBuilder 則可以從 XML 配置文件或一個預(yù)先配置的 Configuration 實(shí)例來構(gòu)建出 SqlSessionFactory 實(shí)例。
-
添加MyBatis的依賴,目前版本是3.4.6,除此之外還有junit和mysql的驅(qū)動依賴分別引入到 pom.xml 文件中
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.qfedu</groupId> <artifactId>Days21Mybatis</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.18</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> </dependencies> </project> -
在resources目錄下新增一個MyBatis的配置文件,mybatis.xml
- 該配置文件中包含一個configuration節(jié)點(diǎn),里面有配置信息,分別是環(huán)境和映射,其中環(huán)境里有datasource,里面有連接數(shù)據(jù)庫的四個字符串
- MySQL 5版本及以下driver的value為com.mysql.jdbc.Driver,6.0版本及以上的value為com.mysql.cj.jdbc.Driver,并在url后面加?serverTimezone=UTC來設(shè)置時區(qū)(不設(shè)置可能報(bào)錯,默認(rèn)為System)
<?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.cj.jdbc.Driver"/> <property name="url" value="數(shù)據(jù)庫url?serverTimezone=UTC"/> <property name="username" value="數(shù)據(jù)庫用戶名"/> <property name="password" value="數(shù)據(jù)庫密碼"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/pojo/UserMapper.xml"/> </mappers> </configuration> -
在com.pojo的包下創(chuàng)建User.java bean文件
public class User { private int uid; private String username; private String password; private int age; private String addr; public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } @Override public String toString() { final StringBuffer sb = new StringBuffer("User{"); sb.append("uid=").append(uid); sb.append(", username='").append(username).append('\''); sb.append(", password='").append(password).append('\''); sb.append(", age=").append(age); sb.append(", addr='").append(addr).append('\''); sb.append('}'); return sb.toString(); } } -
在com/pojo的目錄下創(chuàng)建 UserMapper.xml 文件
- 每個mapper文件都將有一個自己的映射的namespace,每個方法對應(yīng)自己的sql語句,每個sql語句對應(yīng)有一個id
- 整個項(xiàng)目中所有的namespace.id必須是唯一的
<?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"> <mapper namespace="com.pojo.UserMapper"> <select id="selectUser" resultType="com.pojo.User"> select * from user </select> </mapper> -
TestUser.java測試類
- 1.使用MyBatis的配置文件以及SqlSessionFactoryBuilder建造者模式創(chuàng)建SqlSessionFactory對象
- 2.使用SqlSessionFactory對象的openSession()方法來得到一個SqlSession對象,用該對象即可完成對象的所有的crud操作
- 3.使用SqlSession對象來完成crud操作
- 4.關(guān)閉資源
public class TestUser { @Test public void testGetAllUsers(){ try { SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml")); SqlSession session = sf.openSession(); // session的crud方法("namespace.id");整個項(xiàng)目中的namespace.id必須唯一 List<User> users = session.selectList("com.pojo.UserMapper.selectUser"); for (User u : users) { System.out.println(u); } if(session != null){ session.close(); session = null; } } catch (IOException e) { e.printStackTrace(); } } } -
執(zhí)行結(jié)果
User{uid=1, username='aaa', password='111111', age=10, addr='aaaa'} User{uid=2, username='bbb', password='222222', age=11, addr='aaaa'} User{uid=3, username='ccc', password='333333', age=12, addr='aaaa'} User{uid=4, username='ddd', password='444444', age=13, addr='aaaa'} User{uid=5, username='eee', password='555555', age=14, addr='aaaa'} User{uid=6, username='fff', password='666666', age=15, addr='aaaa'} User{uid=7, username='ggg', password='777777', age=16, addr='aaaa'} User{uid=8, username='hhh', password='888888', age=17, addr='aaaa'} User{uid=9, username='iii', password='999999', age=18, addr='aaaa'} User{uid=10, username='jjj', password='000000', age=19, addr='aaaa'} User{uid=11, username='kkk', password='000000', age=20, addr='aaaa'}
三、MyBatis作用域(Scope)和生命周期
-
SqlSessionFactoryBuilder
- 這個類可以被實(shí)例化、使用和丟棄,一旦創(chuàng)建了 SqlSessionFactory,就不再需要它了。
- 因此 SqlSessionFactoryBuilder 實(shí)例的最佳作用域是方法作用域(也就是局部方法變量)。
- 你可以重用 SqlSessionFactoryBuilder 來創(chuàng)建多個 SqlSessionFactory 實(shí)例,但最好還是不要一直保留著它,以保證所有的 XML 解析資源可以被釋放給更重要的事情。
-
SqlSessionFactory
- SqlSessionFactory 一旦被創(chuàng)建就應(yīng)該在應(yīng)用的運(yùn)行期間一直存在,沒有任何理由丟棄它或重新創(chuàng)建另一個實(shí)例。
- 使用 SqlSessionFactory 的最佳實(shí)踐是在應(yīng)用運(yùn)行期間不要重復(fù)創(chuàng)建多次,多次重建 SqlSessionFactory 被視為一種代碼“壞習(xí)慣”。
- 因此 SqlSessionFactory 的最佳作用域是應(yīng)用作用域。 有很多方法可以做到,最簡單的就是使用單例模式或者靜態(tài)單例模式。
-
SqlSession
- 每個線程都應(yīng)該有它自己的 SqlSession 實(shí)例。SqlSession 的實(shí)例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。
- 絕對不能將 SqlSession 實(shí)例的引用放在一個類的靜態(tài)域,甚至一個類的實(shí)例變量也不行。 也絕不能將 SqlSession 實(shí)例的引用放在任何類型的托管作用域中,比如 Servlet 框架中的 HttpSession。
- 如果你現(xiàn)在正在使用一種 Web 框架,考慮將 SqlSession 放在一個和 HTTP 請求相似的作用域中。 換句話說,每次收到 HTTP 請求,就可以打開一個 SqlSession,返回一個響應(yīng)后,就關(guān)閉它。 這個關(guān)閉操作很重要,為了確保每次都能執(zhí)行關(guān)閉操作,你應(yīng)該把這個關(guān)閉操作放到 finally 塊中。
-
映射器實(shí)例
- 映射器是一些綁定映射語句的接口。映射器接口的實(shí)例是從 SqlSession 中獲得的。雖然從技術(shù)層面上來講,任何映射器實(shí)例的最大作用域與請求它們的 SqlSession 相同。
- 但方法作用域才是映射器實(shí)例的最合適的作用域。 也就是說,映射器實(shí)例應(yīng)該在調(diào)用它們的方法中被獲取,使用完畢之后即可丟棄。 映射器實(shí)例并不需要被顯式地關(guān)閉。
- 盡管在整個請求作用域保留映射器實(shí)例不會有什么問題,但是你很快會發(fā)現(xiàn),在這個作用域上管理太多像 SqlSession 的資源會讓你忙不過來。