MyBatis框架核心之(一)基本使用
一、MyBatis框架基本使用
一、 MyBatis簡介
1.MyBatis由來
MyBatis 本是apache的一個開源專案iBatis,2010年這個專案由apache software foundation 遷移到了google code,並且改名為MyBatis。2013年11月遷移到Github。
iBATIS一詞來源於“internet”和“abatis”的組合,是一個基於Java的持久層框架。iBATIS提供的持久層框架包括SQLMaps和Data Access Objects(sDAO)
2.應用範圍
MyBatis 是一款優秀的持久層框架,它支援定製化 SQL、儲存過程以及高階對映。MyBatis 避免了幾乎所有的JDBC 程式碼和手動設定引數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和對映原生資訊,將介面和 Java 的 POJOs(Plain Old Java Objects,普通的Java物件)對映成資料庫中的記錄
3.主要特點:
· 簡單易學:本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只要兩個jar檔案+配置幾個sql對映檔案易於學習,易於使用,通過文件和原始碼,可以比較完全的掌握它的設計思路和實現。
· 靈活:mybatis不會對應用程式或者資料庫的現有設計強加任何影響。 sql寫在xml裡,便於統一管理和優化。通過sql基本上可以實現我們不使用資料訪問框架可以實現的所有功能,或許更多。
· 解除sql與程式程式碼的耦合:通過提供DAL層,將業務邏輯和資料訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試。sql
· 提供對映標籤,支援物件與資料庫的orm欄位關係對映
· 提供物件關係對映標籤,支援物件關係組建維護
· 提供xml標籤,支援編寫動態sql。
4.總體流程
1)載入配置並初始化(載入配置檔案)
(2)接收呼叫請求
(3)處理操作請求(為SQL的ID和傳入引數物件)
(A)根據SQL的ID查詢對應的MappedStatement物件。
(B)根據傳入引數物件解析MappedStatement物件,得到最終要執行的SQL和執行傳入引數。
(C)獲取資料庫連線,根據得到的最終
(D)根據MappedStatement物件中的結果對映配置對得到的執行結果進行轉換處理,並得到最終的處理結果。
(E)釋放連線資源。
(4)返回處理結果將最終的處理結果返回。
二、基本配置
1.引入jar包
核心jar包
Mybatis-3.2.8.jar
相關依賴 |
<!-- mybatis核心jar包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> |
輔助jar包
因為使用mybatis框架後執行過程無法檢視,所以在開發階段為了方便除錯需要使用
debug級別的Log4j將程式碼的執行過程顯示出來,也可以檢視sql語句
slf4j-log4j12.jar |
<!-- slf4j-log4j12 依賴 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version> </dependency> |
mybatis.xml是 Mybatis的大腦,是重要的配置檔案
1).主要配置jdbc環境的配置
configuration 配置
environment環境變數
transactionManager 事務管理器
dataSource 資料來源
2).註冊mapper.xml
<mappers>
<!-- 註冊Mapper.xml檔案 類路徑從src出來 -->
<mapperresource="cn/et/fuqiang/helloworld/myUserMapper.xml"/>
</mappers>
mybatis configuration |
<?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> <!-- 指定jdbc的配置檔案位置 --> <propertiesresource="cn/et/fuqiang/helloworld/jdbc.properties"></properties> <!-- 設定類別名方便mapper設定返回型別--> <typeAliases> <!-- 兩種設定返回型別的方法 --> <!-- 方法一設定返回型別 type類的路徑 alias 要使用的類別名在TypeAliasRegistry.class類中檢視預設設定的類別名 --> <typeAliastype="cn.et.fuqiang.helloworld.User"alias="myUser"/> <!-- 方法二 使用預設的掃包方式 ,設定要掃包的路徑,mybatis會預設把包下面的所有類,以類名首字母小寫的方式設定別名, (較為簡單方便) 使用時可以直接以首字母小寫去使用 --> <package name="cn.fuqiang.entity"/> </typeAliases> <!-- 配置jdbc環境 --> <environmentsdefault="development"> <environmentid="development"> <transactionManagertype="JDBC"/> <!-- 配置資料庫連線資訊 el表示式${}獲取--> <dataSourcetype="POOLED"> <propertyname="driver"value="${driverClass}"/> <propertyname="url"value="${url}"/> <propertyname="username"value="${user}"/> <propertyname="password"value="${password}"/> </dataSource> </environment> </environments> <!-- 設定mapper檔案路徑 --> <mappers> <!-- 註冊Mapper.xml檔案類路徑從src出來 --> <mapperresource="cn/et/fuqiang/helloworld/myUserMapper.xml"/> </mappers> </configuration> |
3.Sql語句的配置檔案 Mapper.xml
1).指定namespace
為這個mapper指定一個唯一的namespace,namespace的值習慣上設定成包名+sql對映檔名,這樣就能夠保證namespace的值是唯一的
例如namespace="me.gacl.mapping.userMapper"就是me.gacl.mapping(包名)+userMapper(userMapper.xml檔案去除字尾)
<mapper namespace="myuser">
……
</mapper>
2).在mapper標籤中可以寫想要執行的SQL語句主要標籤有
<sql id="" ></sql>
<resultMaptype="" id=""></resultMap>
<insertid=""></insert>
<deleteid=""></delete>
<updateid=""></update>
<selectid=""></select>
配置mapper.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"> <!-- 為這個mapper指定一個唯一的namespace,namespace的值習慣上設定成包名+sql對映檔名,這樣就能夠保證namespace的值是唯一的 例如namespace="me.gacl.mapping.userMapper"就是me.gacl.mapping(包名)+userMapper(userMapper.xml檔案去除字尾) --> <mapper namespace="myuser"> <!-- 在select標籤中編寫查詢的SQL語句,設定select標籤的id屬性為getUser,id屬性值必須是唯一的,不能夠重複 使用parameterType屬性指明查詢時使用的引數型別,resultType屬性指明查詢返回的結果集型別 resultType="me.gacl.domain.User"就表示將查詢結果封裝成一個User類的物件返回 User類就是users表所對應的實體類 --> <!-- 根據id查詢得到一個user物件 parameterType 傳入的引數可以是一個任何型別 --> <selectid="selectUserById"parameterType="int"resultType="java.util.Map"> select * from myuser where userid=#{id} </select> <insertid="insertUserByMap"parameterType="java.util.Map"> <!--selectKey是插入語句,和修改語句中特有的標籤 keyProperty key的名字 order BEFORE/AFTER 在insert語句之前或者之後 resultType 查詢語句返回的型別 --> <selectKeykeyProperty="userid"order="BEFORE"resultType="int"> select nvl(max(userid),0)+1 from myuser </selectKey> <!-- 從map中獲取值 #{key}獲取對應的值 --> insert into myuser(userid,username,userage) values(#{userid},#{username},#{userage}) </insert> <deleteid="deleteUserById"parameterType="java.lang.Integer"> delete from myuser where userid=#{id} </delete> <updateid="updateUserByMap"> update myuser set username=#{username},userage=#{userage} whereuserid=#{userid} </update> <!-- 練習使用typeAiase標籤(在mybatis配置檔案中使用) 建立類別名設定返回型別 預設的別名在TypeAliasRegistry.class類中檢視--> <selectid="selectUserGetUser"resultType="myUser"> select * from myuser where userid=#{id} </select> </mapper> |
下面會常用的標籤詳細的解釋
4.java程式碼執行sql
1).獲取一個可以執行對映檔案這種sql的sqlSession
第一種方法 |
//mybatis的配置檔案 String resource = "mybatis.xml"; //使用類載入器載入mybatis的配置檔案(它也載入關聯的對映檔案) InputStream is = 當前類.class.getResourceAsStream(resource); //構建sqlSession的工廠 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is); //建立能執行對映檔案中sql的sqlSession SqlSession session = sessionFactory.openSession(); |
第二種方法 |
//mybatis的配置檔案 String resource = "mybatis.xml"; //使用MyBatis提供的Resources類載入mybatis的配置檔案(它也載入關聯的對映檔案) Reader reader = Resources.getResourceAsReader(resource); //構建sqlSession的工廠 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //建立能執行對映檔案中sql的sqlSession SqlSession session = sessionFactory.openSession(); |
2.執行sql語句的方式
使用session.insert/update/delete/select()執行方法
SqlSession session = getSession(); session.insert/update/delete/select (); |
這只是最基礎的用法,真正的實戰中使用介面對映完成 |
三、mapper.xml配置檔案中常用的sql標籤
1.select標籤屬性簡介
<select resultType="hashmap" resultMap="USER_RESULT_MAP" flushCache="false" useCache="true" timeout="10000" fetchSize="256" statementType="PREPARED" resultSetType="FORWORD_ONLY" ></select> |
2.delete標籤
<delete id id(必須配置) parameterType="" parapeterType(可選配置,預設由mybatis自動選擇處理) databaseId="" 取值範圍oracle|mysql等,表示資料庫廠家,元素內部可通過`<if test="_databaseId = 'oracle'">`來為特定資料庫指定不同的sql語句 lang="" statementType="STATEMENT" statementType(可選配置) timeout="" timeout(可選配置) flushCache="true" flushCache(可選配置) parameterMap="" ></delete> |
3.inert標籤
<insertid="saveUserByMap" parameterType,入參的全限定類名或類型別名 keyColumn,設定資料表自動生成的主鍵名。對特定資料庫(如PostgreSQL),若自動生成的主鍵不是第一個欄位則必須設定 keyProperty,預設值unset,用於設定getGeneratedKeys方法或selectKey子元素返回值將賦值到領域模型的哪個屬性中 useGeneratedKeys,取值範圍true|false(預設值),設定是否使用JDBC的getGenereatedKeys方法獲取主鍵並賦值到keyProperty設定的領域模型屬性中。MySQL和SQLServer執行auto-generated key field,因此當資料庫設定好自增長主鍵後,可通過JDBC的getGeneratedKeys方法獲取。但像Oralce等不支援auto-generated key field的資料庫就不能用這種方法獲取主鍵了 statementType,取值範圍STATEMENT,PREPARED(預設值),CALLABLE flushCache,取值範圍true(預設值)|false,設定執行該操作後是否會清空二級快取和本地快取 timeout,預設為unset(依賴jdbc驅動器的設定),設定執行該操作的最大時限,超時將拋異常 databaseId,取值範圍oracle|mysql等,表示資料庫廠家,元素內部可通過`<if test="_databaseId = 'oracle'">`來為特定資料庫指定不同的sql語句 > </insert> |
4.update標籤
<updateid="" parameterType,入參的全限定類名或類型別名 keyColumn,設定資料表自動生成的主鍵名。對特定資料庫(如PostgreSQL),若自動生成的主鍵不是第一個欄位則必須設定 keyProperty,預設值unset,用於設定getGeneratedKeys方法或selectKey子元素返回值將賦值到領域模型的哪個屬性中 useGeneratedKeys,取值範圍true|false(預設值),設定是否使用JDBC的getGenereatedKeys方法獲取主鍵並賦值到keyProperty設定的領域模型屬性中。MySQL和SQLServer執行auto-generated key field,因此當資料庫設定好自增長主鍵後,可通過JDBC的getGeneratedKeys方法獲取。但像Oralce等不支援auto-generated key field的資料庫就不能用這種方法獲取主鍵了 statementType,取值範圍STATEMENT,PREPARED(預設值),CALLABLE flushCache,取值範圍true(預設值)|false,設定執行該操作後是否會清空二級快取和本地快取 timeout,預設為unset(依賴jdbc驅動器的設定),設定執行該操作的最大時限,超時將拋異常 databaseId,取值範圍oracle|mysql等,表示資料庫廠家,元素內部可通過`<if test="_databaseId = 'oracle'">`來為特定資料庫指定不同的sql語句 ></update> |
5.selectKey標籤
selectKey標籤只在insert標籤和update標籤中存在
作用:在insert元素和update元素中插入查詢語句。 其屬性如下: keyProperty,預設值unset,用於設定getGeneratedKeys方法或selectKey子元素返回值將賦值到領域模型的哪個屬性中 resultType,keyPropety所指向的屬性類全限定類名或類型別名 order屬性,取值範圍BEFORE|AFTER,指定是在insert語句前還是後執行selectKey操作 statementType,取值範圍STATEMENT,PREPARED(預設值),CALLABLE |
例項在插入的時候oracle沒有自增可以用子查詢或查詢序列 |
<insertid="saveUserByMap"> <selectKeykeyProperty="userid"order="BEFORE"resultType="int"> select nvl(max(userid),0)+1 from myuser </selectKey> insert into myuser(userid,username,userage) values(#{userid},#{username},#{userage}) </insert> |
6.重用sql標籤
<sqlid="userColumns">id,username,password</sql>
這個 SQL 片段可以被包含在其他語句中
<selectid="selectProjectList"paramertType="int"resultType="hashmap">
SELECT
<includerefid="userColumns"/>
FROM
t_project_002_project_info
</select>
四、sql語句的編寫與引數的傳遞
Mapper.xml中編寫sql語句
與標準的sql語句一樣
如:Select * fromtablename where column=#{0}/${0}
1.獲取變數
從sql語句中獲取引數有多中方式
不能根據索引取值因為el表示式會把索引當運算的數字
el表示式
${} 只能用在形參中指定的名稱來獲取和 param1 名字
(獲取值得方法相當於字串的拼接如果是字串的話要用引號)
ognl表示式
#{} 可以根據傳入的變數名來獲取值,也可以根據上面兩種方式(獲取值得方法是防注入的,?會用問號代替)
預設是根據形參的索引從0開始
2.可以設定
parameterType 設定傳入的引數型別
可以不設定直接使用即可
3.如果是查詢語句需要設定返回型別resultType
(在TypeAliasRegistry.class中設定了許多類別名,填寫型別的時候可以直接寫別名)
4.java程式碼傳入變數
//@Test public void updateUserByMap() { SqlSession session = getSession(); Map<String,Object> updateMap = new HashMap<String,Object>(); updateMap.put("userid", 1); updateMap.put("username","wfq666"); updateMap.put("userage", 5858518); int update = session.update("updateUserByMap",updateMap); System.out.println(update); session.commit(); } //@Test public void deleteUserById() { SqlSession session = getSession(); int delete = session.delete("deleteUserById", 1); System.out.println(delete); session.commit(); } //@Test public void insertUserByMap() { SqlSession session = getSession(); //建立需要插入的值,key是列名,value 是值 Map<String,Object> insertMap = new HashMap<String,Object>(); //新插入資訊只需要寫入使用者名稱和年齡,id使用selectKey標籤新增 insertMap.put("username","wfq2"); insertMap.put("userage", 100); int insert = session.insert("myuser.insertUserByMap",insertMap); System.out.println(insert); session.commit(); } //@Test public void selectUserById() { SqlSession session = getSession(); /** * 對映sql的標識字串, * myuser.selectUser是myUserMapper.xml檔案中mapper標籤的namespace屬性的值, * getUser是select標籤的id屬性值,通過select標籤的id屬性值就可以找到要執行的SQL */ //執行查詢返回一個唯一user物件的sql Map<String,Object> map= session.selectOne("myuser.selectUserById", 1); System.out.println(map); } @Test public void selectUserGetUser() { SqlSession session = getSession(); //執行查詢返回一個唯一user物 |