mybatis原理概述入門教程
本文我將要介紹一下mybatis的框架原理,以及mybatis的入門程序,實(shí)現(xiàn)用戶的增刪改查,她有什么優(yōu)缺點(diǎn)以及mybatis和hibernate之間存在著怎么樣的關(guān)系,希望對(duì)小伙伴們有幫助,不足之處,還請(qǐng)多多指教。
什么是mybatis?
MyBatis 本是apache的一個(gè)開源項(xiàng)目iBatis, 2010年這個(gè)項(xiàng)目由apache software foundation 遷移到了google code,并且改名為MyBatis 。2013年11月遷移到Github。
MyBatis 是支持定制化 SQL、存儲(chǔ)過程以及高級(jí)映射的優(yōu)秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 代碼和手工設(shè)置參數(shù)以及抽取結(jié)果集。MyBatis 使用簡(jiǎn)單的 XML 或注解來(lái)配置和映射基本體,將接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄。簡(jiǎn)單來(lái)說,mybatis就是一個(gè)持久層的框架,mybatis讓程序?qū)⒅饕Ψ旁趕ql上,通過mybatis提供的映射方式,自由靈活生成滿足需要的sql語(yǔ)句,mybatis可以將向preparedStatement中的輸入?yún)?shù)自動(dòng)進(jìn)行輸入映射,將查詢結(jié)果集靈活映射成java對(duì)象。
接著,我們通過一張圖,來(lái)了解一下mybatis的框架原理:
框架架構(gòu)講解:
a、加載配置文件:配置來(lái)源于兩個(gè)地方,一個(gè)是配置文件,一個(gè)是java代碼的注解,將sql的配置信息加載成為一個(gè)個(gè)MappedStatement對(duì)象(包括了傳入?yún)?shù)映射配置、執(zhí)行的SQL語(yǔ)句、結(jié)果映射配置),存儲(chǔ)在內(nèi)存中。
b、SQL解析:當(dāng)api接口層接收到調(diào)用請(qǐng)求時(shí),會(huì)接收到傳入slq的id和傳入對(duì)象(可以是map或者基本數(shù)據(jù)類型),mybatis會(huì)根據(jù)sql的id找到對(duì)應(yīng)的MappedStatement,然后根據(jù)傳入?yún)?shù)對(duì)象對(duì)MappedStatement進(jìn)行解析,解析后可以得到最終要執(zhí)行的sql語(yǔ)句和參數(shù)。
c、 SQL執(zhí)行:將最終得到的SQL和參數(shù)拿到數(shù)據(jù)庫(kù)進(jìn)行執(zhí)行,得到操作數(shù)據(jù)庫(kù)的結(jié)果。
d、結(jié)果映射:將操作數(shù)據(jù)庫(kù)的結(jié)果按照映射的配置進(jìn)行轉(zhuǎn)換,可以轉(zhuǎn)換成HashMap、JavaBean或者基本數(shù)據(jù)類型,并將最終結(jié)果返回。
mybatis入門程序解析
接著,小編結(jié)合demo來(lái)具體介紹一下,需求如下:
根據(jù)用戶id查詢用戶信息;
根據(jù)用戶名稱模糊查詢用戶信息;
添加、刪除、更新用戶。
第一步、建立各種包和類,工程目錄如下所示:
第二步、編寫SqlMapConfig.xml中的內(nèi)容,配置mybatis的運(yùn)行環(huán)境,數(shù)據(jù)源,事務(wù)等。代碼如下所示:
<span style="font-family:Comic Sans MS;font-size:18px;"><?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> <!-- 將spring整合后environments配置將廢除 --> <environments default="developent"> <!-- 使用jdbc事務(wù)管理,事務(wù)控制由mybatis --> <transactionManager type="JDBC"/> <!-- 數(shù)據(jù)庫(kù)連接池,由mybatis管理 --> <dataSource type="POLLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environments> <!-- 加載 映射文件 --> <mappers> <mapper resource="sqlmap/User.xml"/> </mappers> </configuration> </span>
第三步、編寫User.java中的內(nèi)容,如下所示:
<span style="font-family:Comic Sans MS;font-size:18px;">package cn.itcast.mybatis.po; import java.util.Date; /** * * <p>Title: User</p> * <p>Description:用戶po </p> * @author 丁國(guó)華 * @date 2016年7月31日 15:39:04 * @version 1.0 */ public class User { //屬性名和數(shù)據(jù)庫(kù)表的字段對(duì)應(yīng) private int id; private String username;// 用戶姓名 private String sex;// 性別 private Date birthday;// 生日 private String address;// 地址 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address=" + address + "]"; } } </span>
第四步、實(shí)現(xiàn)增刪改查的功能,首先編寫User.xml中的內(nèi)容,如下所示:
<span style="font-family:Comic Sans MS;font-size:18px;"><?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命名空間,作用就是對(duì)sql進(jìn)行分類化管理,理解sql隔離 注意:使用mapper代理方法開發(fā),namespace有特殊重要的作用--> <mapper namespace="test"> <!-- 在 映射文件中配置很多sql語(yǔ)句 --> <!-- 需求:通過id查詢用戶表的記錄 --> <!-- 通過 select執(zhí)行數(shù)據(jù)庫(kù)查詢 id:標(biāo)識(shí) 映射文件中的 sql 將sql語(yǔ)句封裝到mappedStatement對(duì)象中,所以將id稱為statement的id parameterType:指定輸入 參數(shù)的類型,這里指定int型 #{}表示一個(gè)占位符號(hào) #{id}:其中的id表示接收輸入 的參數(shù),參數(shù)名稱就是id,如果輸入 參數(shù)是簡(jiǎn)單類型,#{}中的參數(shù)名可以任意,可以value或其它名稱 resultType:指定sql輸出結(jié)果 的所映射的java對(duì)象類型,select指定resultType表示將單條記錄映射成的java對(duì)象。 --> <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User"> SELECT * FROM USER WHERE id=#{value} </select> <!-- 根據(jù)用戶名稱模糊查詢用戶信息,可能返回多條 resultType:指定就是單挑記錄所映射的java對(duì)象類型 ${}:表示拼接sql串,將接收到參數(shù)的內(nèi)容不加任何修飾拼接到sql中。 使用${}拼接sql,引起sql注入 ${value}:接收輸入?yún)?shù)的內(nèi)容,如果傳入類型是簡(jiǎn)單類型,${}中只能使用value --> <select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User"> SELECT * FROM USER WHERE username LIKE '%${value}%' </select> <!-- 添加用戶 parameterType:指定輸入?yún)?shù)類型是pojo(包括用戶信息) #{}中指定pojo的屬性名,接收到pojo對(duì)象的屬性值,mybatis通過OGNL獲取對(duì)象的屬性值 --> <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User"> <!-- 將插入數(shù)據(jù)的主鍵返回,返回到user對(duì)象中 SELECT LAST_INSERT_ID():得到剛剛insert進(jìn)去記錄的主鍵值,只適用于自增主鍵 keyProperty:將查詢得到主鍵值設(shè)置到parameterType指定的對(duì)象的那個(gè)屬性 order:SELECT LAST_INSERT_ID()執(zhí)行順序,相對(duì)于insert語(yǔ)句來(lái)說她的執(zhí)行順序 resultType:指定SELECT LAST_INSERT_ID()的結(jié)果類型 --> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> SELECT LAST_INSER_ID() </selectKey> insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address}) <!-- 使用mysql的uuid()函數(shù)生成主鍵 執(zhí)行過程,首先通過uuid得到主鍵,將主鍵設(shè)置到user對(duì)象的id屬性中 其次,在insert執(zhí)行的時(shí)候,從user對(duì)象中,取出id屬性值 --> <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String"> SELECT uuid() </selectKey> insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address}); </insert> <!-- 刪除用戶 根據(jù)id刪除用戶,需要輸入id值 --> <delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id=#{id} </delete> <!-- 根據(jù)id更新用戶 分析: 需要傳入用戶的id 需要傳入用戶的更新信息 parameterType指定user對(duì)象,包括 id和更新信息,注意:id必須存在 #{id}:從輸入 user對(duì)象中獲取id屬性值 --> <update id="updateUser" parameterType="cn.itcast.mybatis.po.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> </mapper></span>
第五步、編寫具體的方法,如下所示:
<span style="font-family:Comic Sans MS;font-size:18px;">package cn.itcast.mybatis.first; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import cn.itcast.mybatis.po.User; public class MybatisFirst { // 根據(jù)id查詢用戶信息,得到一條記錄結(jié)果 @Test public void findUserByIdTest() throws IOException { // mybatis配置文件 String resource = "SqlMapConfig.xml"; // 得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); // 創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); // 通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通過SqlSession操作數(shù)據(jù)庫(kù) // 第一個(gè)參數(shù):映射文件中statement的id,等于=namespace+"."+statement的id // 第二個(gè)參數(shù):指定和映射文件中所匹配的parameterType類型的參數(shù) // sqlSession.selectOne結(jié)果 是與映射文件中所匹配的resultType類型的對(duì)象 // selectOne查詢出一條記錄 User user = sqlSession.selectOne("test.findUserById", 1); System.out.println(user); // 釋放資源 sqlSession.close(); } //根據(jù)用戶名稱模糊查詢用戶列表 @Test public void findUserByNameTest() throws IOException{ //mybatis配置文件 String resource ="SqlMapConfig.xml"; //得到配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); //創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //List中的user和映射文件中德resultType所指定的類型一致 List<User> list = sqlSession.selectList("test.findUserByName","小明"); System.out.println(list); sqlSession.close(); } public void insertUserTest() throws IOException{ //mybatis配置文件 String resource ="SqlMapConfig"; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到sqlsession SqlSession sqlSession = sqlSessionFactory.openSession(); //插入用戶對(duì)象 User user = new User(); user.setUsername("丁國(guó)華"); user.setBirthday(new Date()); user.setSex("1"); user.setAddress("安徽合肥"); //list中的user和映射文件中的resultType所指定的類型一直 sqlSession.insert("test.insertUser",user); //提交事物 sqlSession.commit(); //關(guān)閉會(huì)話 sqlSession.close(); } //根據(jù)id刪除用戶信息 @Test public void deleteUserTest() throws IOException{ //mybatis配置文件 String resource = "SqlMapConfig.xml"; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創(chuàng)建工廠,傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //傳入id刪除用戶 sqlSession.delete("test.deleteUser",39); //提交事物 sqlSession.commit(); //關(guān)閉會(huì)話 sqlSession.close(); } // 更新用戶信息 @Test public void updateUserTest() throws IOException { // mybatis配置文件 String resource = "SqlMapConfig.xml"; // 得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); // 創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); // 通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 更新用戶信息 User user = new User(); //必須設(shè)置id user.setId(41); user.setUsername("丁國(guó)華"); user.setBirthday(new Date()); user.setSex("2"); user.setAddress("安徽合肥"); sqlSession.update("test.updateUser", user); // 提交事務(wù) sqlSession.commit(); // 關(guān)閉會(huì)話 sqlSession.close(); } } </span>
mybatis的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
a、易于上手和掌握。
b、sql寫在xml里,便于統(tǒng)一管理和優(yōu)化。
c、 解除sql與程序代碼的耦合。
d、提供映射標(biāo)簽,支持對(duì)象與數(shù)據(jù)庫(kù)的orm字段關(guān)系映射
e、提供對(duì)象關(guān)系映射標(biāo)簽,支持對(duì)象關(guān)系組建維護(hù)
f、提供xml標(biāo)簽,支持編寫動(dòng)態(tài)sql。
缺點(diǎn):
a、 sql工作量很大,尤其是字段多、關(guān)聯(lián)表多時(shí),更是如此。
b、sql依賴于數(shù)據(jù)庫(kù),導(dǎo)致數(shù)據(jù)庫(kù)移植性差。
c、 由于xml里標(biāo)簽id必須唯一,導(dǎo)致DAO中方法不支持方法重載。
d、DAO層過于簡(jiǎn)單,對(duì)象組裝的工作量較大。
e、 緩存使用不當(dāng),容易產(chǎn)生臟數(shù)據(jù)。
mybatis和hibernate的對(duì)比
相同點(diǎn):Hibernate和mybatis都可以是通過SessionFactoryBuilder由xml配置文件生成SessionFactory,然后由SessionFactroy生成Session,最后由Session來(lái)開啟執(zhí)行事物和SQL語(yǔ)句,其中SessionFactoryBuider、SessionFactory、Session的生命周期都是差不多的。
不同點(diǎn):
mybatis:小巧、方便、高效、簡(jiǎn)單、直接、半自動(dòng);
hibernate:強(qiáng)大、方便、高效、復(fù)雜、繞彎子、全自動(dòng);
mybatis:
a、入門簡(jiǎn)單,即學(xué)即用,提供了數(shù)據(jù)庫(kù)查詢的自動(dòng)對(duì)象綁定功能,而且延續(xù)了很多的SQL使用經(jīng)驗(yàn),對(duì)于沒有那么高的對(duì)象模型要求的項(xiàng)目來(lái)說,堪稱perfect。
b、 可以進(jìn)行更為細(xì)致的SQL優(yōu)化,可以減少查詢字段。
c、 缺點(diǎn)就是框架還是比較簡(jiǎn)陋,功能尚有缺失,雖然簡(jiǎn)化了數(shù)據(jù)綁定代碼,但是整個(gè)底層數(shù)據(jù)庫(kù)查詢實(shí)際還是要自己寫的,工作量也比較大,而且不太容易適應(yīng)快速數(shù)據(jù)庫(kù)修改。
d、 二級(jí)緩存機(jī)制不佳。
hibernate:
a、功能強(qiáng)大,數(shù)據(jù)庫(kù)無(wú)關(guān)性好,O/R映射能力強(qiáng),如果你對(duì)Hibernate相當(dāng)精通,而且對(duì)Hibernate進(jìn)行了適當(dāng)?shù)姆庋b,那么你的項(xiàng)目整個(gè)持久層代碼會(huì)相當(dāng)簡(jiǎn)單,需要寫的代碼很,開發(fā)速度很快,非常爽。
b、有更好的二級(jí)緩存機(jī)制,可以使用第三方緩存。
c、缺點(diǎn)就是學(xué)習(xí)門檻不低,要精通門檻更高,而且怎么設(shè)計(jì)O/R映射,在性能和對(duì)象模型之間如何權(quán)衡取得平衡,以及怎樣用好Hibernate方面需要你的經(jīng)驗(yàn)和能力都很強(qiáng)才行。
舉個(gè)形象的比喻:
mybatis:機(jī)械工具,使用方便,拿來(lái)就用,但工作還是要自己來(lái)作,不過工具是活的,怎么使由我決定。
hibernate:智能機(jī)器人,但研發(fā)它(學(xué)習(xí)、熟練度)的成本很高,工作都可以擺脫他了,但僅限于它能做的事。
小編寄語(yǔ):該博文,小編主要簡(jiǎn)單的介紹了mybatis的基本知識(shí),包括一個(gè)簡(jiǎn)單的增刪改查的demo,mybatis的優(yōu)缺點(diǎn),以及hibernate和mybatis的對(duì)比,她們之間的相同點(diǎn)和不同,mybatis簡(jiǎn)單來(lái)說,就是一個(gè)持久層的框架,mybatis讓程序?qū)⒅饕Ψ旁趕ql上,通過mybatis提供的映射方式,自由靈活生成滿足需要的sql語(yǔ)句,mybatis可以將向preparedStatement中的輸入?yún)?shù)自動(dòng)進(jìn)行輸入映射,將查詢結(jié)果集靈活映射成java對(duì)象。
以上所述是小編給大家介紹的mybatis原理概述入門教程,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
淺談Java數(shù)值類型的轉(zhuǎn)換與強(qiáng)制轉(zhuǎn)換
這篇文章主要介紹了Java數(shù)值類型的轉(zhuǎn)換與強(qiáng)制轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04Java實(shí)現(xiàn)多線程大批量同步數(shù)據(jù)(分頁(yè))
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多線程大批量同步數(shù)據(jù)(分頁(yè)),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08關(guān)于Java中XML Namespace 命名空間問題
這篇文章主要介紹了Java中XML Namespace 命名空間,XML命名空間是由國(guó)際化資源標(biāo)識(shí)符 (IRI) 標(biāo)識(shí)的 XML 元素和屬性集合,該集合通常稱作 XML“詞匯”,對(duì)XML Namespace 命名空間相關(guān)知識(shí)感興趣的朋友一起看看吧2021-08-08Java中的強(qiáng)引用,軟引用,弱引用,虛引用的作用介紹
這篇文章主要介紹了Java中的強(qiáng)引用,軟引用,弱引用,虛引用的作用,下文內(nèi)容具有一定的知識(shí)參考價(jià)值,需要的小伙伴可以參考一下,希望對(duì)你有所幫助2022-02-02