本文我將要介紹一下mybatis的框架原理,以及mybatis的入門程序,實現用戶的增刪改查,她有什么優缺點以及mybatis和hibernate之間存在著怎么樣的關系,希望對小伙伴們有幫助,不足之處,還請多多指教。
什么是mybatis?
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,并且改名為MyBatis 。2013年11月遷移到Github。
MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 代碼和手工設置參數以及抽取結果集。MyBatis 使用簡單的 XML 或注解來配置和映射基本體,將接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。簡單來說,mybatis就是一個持久層的框架,mybatis讓程序將主要精力放在sql上,通過mybatis提供的映射方式,自由靈活生成滿足需要的sql語句,mybatis可以將向preparedStatement中的輸入參數自動進行輸入映射,將查詢結果集靈活映射成java對象。
接著,我們通過一張圖,來了解一下mybatis的框架原理:
框架架構講解:
a、加載配置文件:配置來源于兩個地方,一個是配置文件,一個是java代碼的注解,將sql的配置信息加載成為一個個MappedStatement對象(包括了傳入參數映射配置、執行的SQL語句、結果映射配置),存儲在內存中。
b、SQL解析:當api接口層接收到調用請求時,會接收到傳入slq的id和傳入對象(可以是map或者基本數據類型),mybatis會根據sql的id找到對應的MappedStatement,然后根據傳入參數對象對MappedStatement進行解析,解析后可以得到最終要執行的sql語句和參數。
c、 SQL執行:將最終得到的SQL和參數拿到數據庫進行執行,得到操作數據庫的結果。
d、結果映射:將操作數據庫的結果按照映射的配置進行轉換,可以轉換成HashMap、JavaBean或者基本數據類型,并將最終結果返回。
mybatis入門程序解析
接著,小編結合demo來具體介紹一下,需求如下:
根據用戶id查詢用戶信息;
根據用戶名稱模糊查詢用戶信息;
添加、刪除、更新用戶。
第一步、建立各種包和類,工程目錄如下所示:
第二步、編寫SqlMapConfig.xml中的內容,配置mybatis的運行環境,數據源,事務等。代碼如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<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事務管理,事務控制由mybatis --> <transactionManager type= "JDBC" /> <!-- 數據庫連接池,由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中的內容,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
<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 丁國華 * @date 2016年7月31日 15:39:04 * @version 1.0 */ public class User { //屬性名和數據庫表的字段對應 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> |
第四步、實現增刪改查的功能,首先編寫User.xml中的內容,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<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命名空間,作用就是對sql進行分類化管理,理解sql隔離 注意:使用mapper代理方法開發,namespace有特殊重要的作用--> <mapper namespace= "test" > <!-- 在 映射文件中配置很多sql語句 --> <!-- 需求:通過id查詢用戶表的記錄 --> <!-- 通過 select執行數據庫查詢 id:標識 映射文件中的 sql 將sql語句封裝到mappedStatement對象中,所以將id稱為statement的id parameterType:指定輸入 參數的類型,這里指定 int 型 #{}表示一個占位符號 #{id}:其中的id表示接收輸入 的參數,參數名稱就是id,如果輸入 參數是簡單類型,#{}中的參數名可以任意,可以value或其它名稱 resultType:指定sql輸出結果 的所映射的java對象類型,select指定resultType表示將單條記錄映射成的java對象。 --> <select id= "findUserById" parameterType= "int" resultType= "cn.itcast.mybatis.po.User" > SELECT * FROM USER WHERE id=#{value} </select> <!-- 根據用戶名稱模糊查詢用戶信息,可能返回多條 resultType:指定就是單挑記錄所映射的java對象類型 ${}:表示拼接sql串,將接收到參數的內容不加任何修飾拼接到sql中。 使用${}拼接sql,引起sql注入 ${value}:接收輸入參數的內容,如果傳入類型是簡單類型,${}中只能使用value --> <select id= "findUserByName" parameterType= "java.lang.String" resultType= "cn.itcast.mybatis.po.User" > SELECT * FROM USER WHERE username LIKE '%${value}%' </select> <!-- 添加用戶 parameterType:指定輸入參數類型是pojo(包括用戶信息) #{}中指定pojo的屬性名,接收到pojo對象的屬性值,mybatis通過OGNL獲取對象的屬性值 --> <insert id= "insertUser" parameterType= "cn.itcast.mybatis.po.User" > <!-- 將插入數據的主鍵返回,返回到user對象中 SELECT LAST_INSERT_ID():得到剛剛insert進去記錄的主鍵值,只適用于自增主鍵 keyProperty:將查詢得到主鍵值設置到parameterType指定的對象的那個屬性 order:SELECT LAST_INSERT_ID()執行順序,相對于insert語句來說她的執行順序 resultType:指定SELECT LAST_INSERT_ID()的結果類型 --> <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()函數生成主鍵 執行過程,首先通過uuid得到主鍵,將主鍵設置到user對象的id屬性中 其次,在insert執行的時候,從user對象中,取出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> <!-- 刪除用戶 根據id刪除用戶,需要輸入id值 --> <delete id= "deleteUser" parameterType= "java.lang.Integer" > delete from user where id=#{id} </delete> <!-- 根據id更新用戶 分析: 需要傳入用戶的id 需要傳入用戶的更新信息 parameterType指定user對象,包括 id和更新信息,注意:id必須存在 #{id}:從輸入 user對象中獲取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> |
第五步、編寫具體的方法,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
<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 { // 根據id查詢用戶信息,得到一條記錄結果 @Test public void findUserByIdTest() throws IOException { // mybatis配置文件 String resource = "SqlMapConfig.xml" ; // 得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); // 創建會話工廠,傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); // 通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通過SqlSession操作數據庫 // 第一個參數:映射文件中statement的id,等于=namespace+"."+statement的id // 第二個參數:指定和映射文件中所匹配的parameterType類型的參數 // sqlSession.selectOne結果 是與映射文件中所匹配的resultType類型的對象 // selectOne查詢出一條記錄 User user = sqlSession.selectOne( "test.findUserById" , 1 ); System.out.println(user); // 釋放資源 sqlSession.close(); } //根據用戶名稱模糊查詢用戶列表 @Test public void findUserByNameTest() throws IOException{ //mybatis配置文件 String resource = "SqlMapConfig.xml" ; //得到配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); //創建會話工廠,傳入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); //創建會話工廠,傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到sqlsession SqlSession sqlSession = sqlSessionFactory.openSession(); //插入用戶對象 User user = new User(); user.setUsername( "丁國華" ); user.setBirthday( new Date()); user.setSex( "1" ); user.setAddress( "安徽合肥" ); //list中的user和映射文件中的resultType所指定的類型一直 sqlSession.insert( "test.insertUser" ,user); //提交事物 sqlSession.commit(); //關閉會話 sqlSession.close(); } //根據id刪除用戶信息 @Test public void deleteUserTest() throws IOException{ //mybatis配置文件 String resource = "SqlMapConfig.xml" ; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創建工廠,傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //傳入id刪除用戶 sqlSession.delete( "test.deleteUser" , 39 ); //提交事物 sqlSession.commit(); //關閉會話 sqlSession.close(); } // 更新用戶信息 @Test public void updateUserTest() throws IOException { // mybatis配置文件 String resource = "SqlMapConfig.xml" ; // 得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); // 創建會話工廠,傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); // 通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 更新用戶信息 User user = new User(); //必須設置id user.setId( 41 ); user.setUsername( "丁國華" ); user.setBirthday( new Date()); user.setSex( "2" ); user.setAddress( "安徽合肥" ); sqlSession.update( "test.updateUser" , user); // 提交事務 sqlSession.commit(); // 關閉會話 sqlSession.close(); } } </span> |
mybatis的優缺點
優點:
a、易于上手和掌握。
b、sql寫在xml里,便于統一管理和優化。
c、 解除sql與程序代碼的耦合。
d、提供映射標簽,支持對象與數據庫的orm字段關系映射
e、提供對象關系映射標簽,支持對象關系組建維護
f、提供xml標簽,支持編寫動態sql。
缺點:
a、 sql工作量很大,尤其是字段多、關聯表多時,更是如此。
b、sql依賴于數據庫,導致數據庫移植性差。
c、 由于xml里標簽id必須唯一,導致DAO中方法不支持方法重載。
d、DAO層過于簡單,對象組裝的工作量較大。
e、 緩存使用不當,容易產生臟數據。
mybatis和hibernate的對比
相同點:Hibernate和mybatis都可以是通過SessionFactoryBuilder由xml配置文件生成SessionFactory,然后由SessionFactroy生成Session,最后由Session來開啟執行事物和SQL語句,其中SessionFactoryBuider、SessionFactory、Session的生命周期都是差不多的。
不同點:
mybatis:小巧、方便、高效、簡單、直接、半自動;
hibernate:強大、方便、高效、復雜、繞彎子、全自動;
mybatis:
a、入門簡單,即學即用,提供了數據庫查詢的自動對象綁定功能,而且延續了很多的SQL使用經驗,對于沒有那么高的對象模型要求的項目來說,堪稱perfect。
b、 可以進行更為細致的SQL優化,可以減少查詢字段。
c、 缺點就是框架還是比較簡陋,功能尚有缺失,雖然簡化了數據綁定代碼,但是整個底層數據庫查詢實際還是要自己寫的,工作量也比較大,而且不太容易適應快速數據庫修改。
d、 二級緩存機制不佳。
hibernate:
a、功能強大,數據庫無關性好,O/R映射能力強,如果你對Hibernate相當精通,而且對Hibernate進行了適當的封裝,那么你的項目整個持久層代碼會相當簡單,需要寫的代碼很,開發速度很快,非常爽。
b、有更好的二級緩存機制,可以使用第三方緩存。
c、缺點就是學習門檻不低,要精通門檻更高,而且怎么設計O/R映射,在性能和對象模型之間如何權衡取得平衡,以及怎樣用好Hibernate方面需要你的經驗和能力都很強才行。
舉個形象的比喻:
mybatis:機械工具,使用方便,拿來就用,但工作還是要自己來作,不過工具是活的,怎么使由我決定。??
hibernate:智能機器人,但研發它(學習、熟練度)的成本很高,工作都可以擺脫他了,但僅限于它能做的事。
小編寄語:該博文,小編主要簡單的介紹了mybatis的基本知識,包括一個簡單的增刪改查的demo,mybatis的優缺點,以及hibernate和mybatis的對比,她們之間的相同點和不同,mybatis簡單來說,就是一個持久層的框架,mybatis讓程序將主要精力放在sql上,通過mybatis提供的映射方式,自由靈活生成滿足需要的sql語句,mybatis可以將向preparedStatement中的輸入參數自動進行輸入映射,將查詢結果集靈活映射成java對象。
以上所述是小編給大家介紹的mybatis原理概述入門教程,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!