MyBatis入門(一)—— 入門案例


一、MyBatis簡介

  MyBatis是面向sql的持久層框架,他封裝了jdbc訪問數據庫的過程,我們開發,只需專注於sql語句本身的拼裝,其它賦值的過程全部可以交給MyBatis去完成。

  與Hibernate比較:

1.Hibernate學習門檻不低,要精通門檻更高。門檻高在怎么設計O/R映射,在性能和對象模型之間如何權衡取得平衡,以及怎樣用好Hibernate緩存與數據加載策略方面需要你的經驗和能力都很強才行。國內目前前的情況精通hibernate技術大牛非常少。

2.sql優化方面,Hibernate的查詢會將表中的所有字段查詢出來,這一點會有性能消耗。當然了,Hibernate也可以自己寫SQL來指定需要查詢的字段,但這樣就破壞了Hibernate開發的簡潔性。說得更深入一些,如果有個查詢要關聯多張表,比如5張表,10張表時,而且,我們要取的字段只是其中幾張表的部分字段。這時用hibernate時就會顯得非常力不從心。就算用hibernate的sqlquery,后續的維護工作也會讓人發狂。

二、入門案例

1、數據庫的准備(創表語句)

 1 -- ----------------------------
 2 -- Table structure for `user`
 3 -- ----------------------------
 4 DROP TABLE IF EXISTS `user`;
 5 CREATE TABLE `user` (
 6   `id` int(11) NOT NULL AUTO_INCREMENT,
 7   `username` varchar(32) NOT NULL COMMENT '用戶名稱',
 8   `birthday` date DEFAULT NULL COMMENT '生日',
 9   `sex` char(1) DEFAULT NULL COMMENT '性別',
10   `address` varchar(256) DEFAULT NULL COMMENT '地址',
11   PRIMARY KEY (`id`)
12 ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
13 
14 -- ----------------------------
15 -- Records of user
16 -- ----------------------------
17 INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
18 INSERT INTO `user` VALUES ('10', '張三', '2014-07-10', '1', '北京市');
19 INSERT INTO `user` VALUES ('16', '張小明', null, '1', '河南鄭州');
20 INSERT INTO `user` VALUES ('22', '陳小明', null, '1', '河南鄭州');
21 INSERT INTO `user` VALUES ('24', '張三豐', null, '1', '河南鄭州');
22 INSERT INTO `user` VALUES ('25', '陳小明', null, '1', '河南鄭州');
23 INSERT INTO `user` VALUES ('26', '王五', null, null, null);

2、使用idea新建maven-archetype-quickstart項目

3、引入依賴

 1 <dependency>
 2       <groupId>mysql</groupId>
 3       <artifactId>mysql-connector-java</artifactId>
 4       <version>5.1.45</version>
 5 </dependency>
 6 <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
 7 <dependency>
 8       <groupId>org.mybatis</groupId>
 9       <artifactId>mybatis</artifactId>
10       <version>3.2.7</version>
11 </dependency>

4、於resources文件夾中創建SqlMapConfig.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6     <!-- 和spring整合后 environments配置將廢除 -->
 7     <environments default="development">
 8         <environment id="development">
 9             <!-- 使用jdbc事務管理 -->
10             <transactionManager type="JDBC" />
11             <!-- 數據庫連接池 -->
12             <dataSource type="POOLED">
13                 <property name="driver" value="com.mysql.jdbc.Driver" />
14                 <property name="url"
15                           value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
16                 <property name="username" value="root" />
17                 <property name="password" value="" />
18             </dataSource>
19         </environment>
20     </environments>
21 
22     <mappers>
23         <!-- 第一種方式,加載 resource-->
24         <mapper resource="User.xml"></mapper>
25         <mapper resource="UserMapper.xml"/>
26 
27         <!-- 第三種方式,包掃描器要求(推薦使用此方式):
28              1、映射文件與接口同一目錄下
29              2、映射文件名必需與接口文件名稱一致
30         -->
31         <!--<package name="com.cenobitor.mapper"/>-->
32     </mappers>
33 </configuration>

5、創建實體類User

 1 package com.cenobitor.pojo;
 2 
 3 import java.util.Date;
 4 
 5 public class User {
 6 
 7     private Integer id;
 8     private String username;// 用戶姓名
 9     private String sex;// 性別
10     private Date birthday;// 生日
11     private String address;// 地址
12     private String uuid;
13 
14     ......
15 }

6、配置SQL查詢的映射文件(resources目錄)

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper
 3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <!-- namespace:命名空間,類似於java包,主要用於隔離sql語句的,后續有重要作用
 6      #{}:占位符,相當於jdbc的?
 7      ${}:字符串拼接指令,注意如果入參為普通數據類型時,括號里面只能寫value
 8  -->
 9 <mapper namespace="user">
10     <!-- id:sql id標識sql語句的唯一標識
11              parameterType:入參的數據類型
12              resultType:返回結果的數據類型
13     -->
14     <select id="getUserById" parameterType="int" resultType="com.cenobitor.pojo.User">
15         SELECT
16           `id`,
17           `username`,
18           `birthday`,
19           `sex`,
20           `address`
21         FROM `user`
22         WHERE id = #{id}
23     </select>
24 
25     <!-- resultType:如果返回結果是集合時,只需要設置為元素的數據類型就可 -->
26     <select id="getUserByName" parameterType="String" resultType="com.cenobitor.pojo.User">
27         SELECT
28           `id`,
29           `username`,
30           `birthday`,
31           `sex`,
32           `address`
33         FROM `user`
34         WHERE username LIKE '%${value}%'
35     </select>
36     
37     <insert id="insertUser" parameterType="com.cenobitor.pojo.User">
38         INSERT INTO USER (`username`,`birthday`,`sex`,`address`)
39         VALUES (#{username},#{birthday},#{sex},#{address})
40     </insert>
41 
42     <!--返回MySql自增主鍵-->
43     <!-- useGeneratedKeys:標識插入使用自增id
44          keyProperty:與useGeneratedKeys配套使用,用於綁定主鍵接收的pojo屬性
45      -->
46     <insert id="insertUserKey" parameterType="com.cenobitor.pojo.User"
47             useGeneratedKeys="true" keyProperty="id">
48 
49         <!-- selectKey:用於配置主鍵返回
50                       keyProperty:要綁定的pojo屬性
51                       resultType:屬性數據類型
52                       order:指定什么時候執行,AFTER之后
53                  -->
54         <!-- <selectKey keyProperty="id" resultType="int" order="AFTER">
55              SELECT LAST_INSERT_ID()
56         </selectKey> -->
57 
58         INSERT INTO USER (`username`,`birthday`,`sex`,`address`)
59         VALUES (#{username},#{birthday},#{sex},#{address})
60     </insert>
61 
62     <!--返回MySql的uuid返回主鍵-->
63     <insert id="insertUserUUID" parameterType="com.cenobitor.pojo.User">
64 
65         <!-- selectKey:用於配置主鍵返回
66                       keyProperty:要綁定的pojo屬性
67                       resultType:屬性數據類型
68                       order:指定什么時候執行,AFTER之后
69                  -->
70         <selectKey keyProperty="uuid" resultType="String" order="BEFORE">
71              SELECT UUID()
72         </selectKey>
73 
74         INSERT INTO USER (`username`,`birthday`,`sex`,`address`,`uuid`)
75         VALUES (#{username},#{birthday},#{sex},#{address},#{uuid})
76     </insert>
77     
78     <update id="updateUser" parameterType="com.cenobitor.pojo.User">
79         UPDATE USER SET username = #{username} WHERE id = #{id}
80     </update>
81     
82     <delete id="deleteUser" parameterType="com.cenobitor.pojo.User">
83         DELETE FROM `user` WHERE `id` = #{id}
84     </delete>
85 
86 </mapper>

7、加載映射文件,在SqlMapConfig.xml配置mappers節點

8、編寫測試類

  1 package com.cenobitor;
  2 
  3 import com.cenobitor.Utils.SqlSessionFactoryUtils;
  4 import com.cenobitor.pojo.User;
  5 import junit.framework.Test;
  6 import junit.framework.TestCase;
  7 import junit.framework.TestSuite;
  8 import org.apache.ibatis.io.Resources;
  9 import org.apache.ibatis.session.SqlSession;
 10 import org.apache.ibatis.session.SqlSessionFactory;
 11 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 12 
 13 import java.io.IOException;
 14 import java.io.InputStream;
 15 import java.util.Date;
 16 import java.util.List;
 17 
 18 /**
 19  * Unit test for simple App.
 20  */
 21 public class AppTest extends TestCase {
 22     //根據id查找用戶
 23     public void testGetUserById() throws IOException {
 24 
 25         //創建SqlSessionFactoryBuilder對象
 26         SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
 27         //查找配置文件,創建輸入流
 28         InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
 29         //加載配置文件,創建SqlSessionFactory
 30         SqlSessionFactory sqlSessionFactory = sfb.build(inputStream);
 31         //創建SqlSession
 32         SqlSession sqlSession = sqlSessionFactory.openSession();
 33         //執行查詢,參數一:要查詢的statementId,參數二:sql語句入參
 34         User user = sqlSession.selectOne("user.getUserById", 1);
 35         //輸入查詢結果
 36         System.out.println(user);
 37 
 38         //釋放資源
 39         sqlSession.close();
 40     }
 41 
 42     //根據用戶名查找用戶列表
 43     public void testGetUserByName(){
 44         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
 45         SqlSession sqlSession = sqlSessionFactory.openSession();
 46         List<User> list = sqlSession.selectList("user.getUserByName", "張");
 47         for (User user : list) {
 48             System.out.println(user);
 49         }
 50 
 51         sqlSession.close();
 52     }
 53 
 54     //插入用戶
 55     public void testInsertUser(){
 56         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
 57         SqlSession sqlSession = sqlSessionFactory.openSession();
 58 
 59         User user = new User();
 60         user.setUsername("貂蟬");
 61         user.setSex("0");
 62         user.setBirthday(new Date());
 63         user.setAddress("呂布");
 64 
 65         //執行插入語句
 66         sqlSession.insert("user.insertUser",user);
 67         //提交事務
 68         sqlSession.commit();
 69         //釋放資源
 70         sqlSession.close();
 71     }
 72 
 73     //Mysql自增返回
 74     public void testInsertUserKey(){
 75         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
 76         SqlSession sqlSession = sqlSessionFactory.openSession();
 77 
 78         User user = new User();
 79         user.setUsername("楊玉環");
 80         user.setSex("0");
 81         user.setBirthday(new Date());
 82         user.setAddress("李隆基");
 83 
 84         //執行插入語句
 85         sqlSession.insert("user.insertUserKey", user);
 86         System.out.println(user);
 87         //提交事務
 88         sqlSession.commit();
 89         //釋放資源
 90         sqlSession.close();
 91     }
 92 
 93     //Mysql的uuid返回主鍵
 94     //注:在使用uuid之前數據庫user表要先加上uuid2字段、user的pojo也要加上相應屬性
 95     public void testInsertUserUUID(){
 96         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
 97         SqlSession sqlSession = sqlSessionFactory.openSession();
 98 
 99         User user = new User();
100         user.setUsername("孫尚香");
101         user.setSex("0");
102         user.setBirthday(new Date());
103         user.setAddress("劉備");
104 
105         //執行插入語句
106         sqlSession.insert("user.insertUserUUID", user);
107         System.out.println(user);
108         //提交事務
109         sqlSession.commit();
110         //釋放資源
111         sqlSession.close();
112     }
113 
114     //修改用戶
115     public void testUpdateUser(){
116         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
117         SqlSession sqlSession = sqlSessionFactory.openSession();
118 
119         User user = new User();
120         user.setUsername("呂雉");
121         user.setId(32);
122 
123         //執行插入語句
124         sqlSession.update("user.updateUser",user);
125 
126         //提交事務
127         sqlSession.commit();
128         //釋放資源
129         sqlSession.close();
130     }
131 
132     //刪除用戶
133     public void testDeleteUser(){
134         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
135         SqlSession sqlSession = sqlSessionFactory.openSession();
136         sqlSession.delete("user.deleteUser",32);
137         sqlSession.commit();
138         sqlSession.close();
139     }
140 }

9、抽取SqlSessionFactoryUtils工具類,共享SqlSessionFactory的對象

 1 public class SqlSessionFactoryUtils {
 2     private SqlSessionFactoryUtils(){}
 3 
 4     private static class SqlSessionFactoryInstance{
 5 
 6         public static SqlSessionFactory sqlSessionFactory;
 7 
 8         static {
 9             try {
10                 sqlSessionFactory =  new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml"));
11             } catch (IOException e) {
12                 e.printStackTrace();
13             }
14         }
15     }
16 
17     public static SqlSessionFactory getSqlSessionFactory(){
18         return SqlSessionFactoryInstance.sqlSessionFactory;
19     }
20 
21 }

三、MyBatis架構圖

四、MyBatis 動態代理Dao開發 

 1、開發規則

  • namespace必須是接口的全路徑名
  • 接口的方法名必須與映射文件的sql id 一致
  • 接口的輸入參數必須與映射文件的parameterType類型一致
  • 接口的返回類型必須與映射文件的resultType類型一致

2、動態代理Dao開發步驟

①創建UserMapper.xml映射文件

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper
 3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="com.cenobitor.mapper.UserMapper">
 6 
 7     <select id="getUserById" parameterType="int" resultType="com.cenobitor.pojo.User">
 8         SELECT
 9           `id`,
10           `username`,
11           `birthday`,
12           `sex`,
13           `address`
14         FROM `user`
15         WHERE id = #{id}
16     </select>
17 
18     <select id="getUserByName" parameterType="String" resultType="com.cenobitor.pojo.User">
19         SELECT
20           `id`,
21           `username`,
22           `birthday`,
23           `sex`,
24           `address`
25         FROM `user`
26         WHERE username LIKE '%${value}%'
27     </select>
28     
29     <insert id="insertUser" parameterType="com.cenobitor.pojo.User">
30         INSERT INTO USER (`username`,`birthday`,`sex`,`address`)
31         VALUES (#{username},#{birthday},#{sex},#{address})
32     </insert>
33 
34 </mapper>

②創建UserMapper接口

 1 package com.cenobitor.mapper;
 2 
 3 import com.cenobitor.pojo.User;
 4 import java.util.List;
 5 
 6 public interface UserMapper {
 7 
 8     /**根據用戶ID查詢用戶信息
 9      * @param id
10      * @return
11      */
12     User getUserById(Integer id);
13 
14     /**
15      * 根據用戶名查找用戶列表
16      * @param name
17      * @return
18      */
19     List<User> getUserByName(String name);
20 
21     /**
22      * 添加用戶
23      * @param user
24      */
25     void insertUser(User user);
26 
27 }

③加載UserMpper.xml

 

④建立測試類

 1 public class UserMapperTest {
 2 
 3     @Test
 4     public void getUserById() {
 5         SqlSessionFactory sqlSessionFactory =
 6                 SqlSessionFactoryUtils.getSqlSessionFactory();
 7         SqlSession sqlSession = sqlSessionFactory.openSession();
 8         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
 9         User user = mapper.getUserById(31);
10         System.out.println(user);//User{id=31, username='楊玉環', sex='0', birthday=Sat Apr 07 00:00:00 CST 2018, address='李隆基', uuid='null'}
11         sqlSession.close();
12     }
13 
14     @Test
15     public void getUserByName() {
16         SqlSessionFactory sqlSessionFactory =
17                 SqlSessionFactoryUtils.getSqlSessionFactory();
18         SqlSession sqlSession = sqlSessionFactory.openSession();
19         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
20         List<User> users = mapper.getUserByName("張");
21         for (User user : users) {
22             System.out.println(user);
23         }
24         /*User{id=10, username='張三', sex='1', birthday=Thu Jul 10 00:00:00 CST 2014, address='北京市', uuid='null'}
25         User{id=16, username='張小明', sex='1', birthday=null, address='河南鄭州', uuid='null'}
26         User{id=24, username='張三豐', sex='1', birthday=null, address='河南鄭州', uuid='null'}*/
27         sqlSession.close();
28     }
29 
30     @Test
31     public void insertUser() {
32         SqlSessionFactory sqlSessionFactory =
33                 SqlSessionFactoryUtils.getSqlSessionFactory();
34         SqlSession sqlSession = sqlSessionFactory.openSession();
35         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
36         User user = new User();
37         user.setUsername("lisi");
38         user.setSex("1");
39         user.setBirthday(new Date());
40         user.setAddress("北京");
41         mapper.insertUser(user);
42         sqlSession.commit();
43         sqlSession.close();
44     }
45 }

五、SqlMapConfig.xml配置

1、properties

①屬於核心文件配置

1 <!-- 加載規則,首先加載標簽內部屬性,再加載外部文件,名稱相同時,會替換相同名稱的內容 -->
2     <properties resource="jdbc.properties">
3         <property name="jdbc.username" value="root1"/>
4         <property name="jdbc.password" value="root"/>
5     </properties>

②jdbc.properties

1     jdbc.driver=com.mysql.jdbc.Driver
2     jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
3     jdbc.username=root
4     jdbc.password=root

2、typeAliases

自定義別名

1 <typeAliases>
2         <!-- 單個別名定義 -->
3         <!-- <typeAlias type="com.itheima.mybatis.pojo.User" alias="user"/> -->
4         <!-- 別名包掃描器(推薦使用此方式),整個包下的類都被定義別名,別名為類名,不區分大小寫-->
5         <package name="com.itheima.mybatis.pojo"/>
6 </typeAliases>

3、mapper

 1 <mappers>
 2         <!-- 第一種方式,加載 resource-->
 3         <mapper resource="mapper/user.xml"/>
 4         <!-- <mapper resource="mapper/UserMapper.xml"/> -->
 5 
 6         <!-- 第二種方式,class掃描器要求:
 7              1、映射文件與接口同一目錄下
 8              2、映射文件名必需與接口文件名稱一致
 9          -->
10         <!-- <mapper class="com.itheima.mybatis.mapper.UserMapper"/> -->
11 
12         <!-- 第三種方式,包掃描器要求(推薦使用此方式):
13              1、映射文件與接口同一目錄下
14              2、映射文件名必需與接口文件名稱一致
15         -->
16         <package name="com.itheima.mybatis.mapper"/>
17 </mappers>

 六、小結

1、#{} 和${}

#{} 表示一個占位符號,通過#{} 可以實現preparedStatement向占位符中設置值,自動進行java類型和jdbc類型轉換。#{} 可以有效防止sql注入。#{}可以接受簡單類型值或pojo屬性值。如果parameterType傳輸單個簡單類型值,#{}括號中可以是value或其他名稱。

${}表示拼接sql串,通過${}可以將parameterType傳入的內容拼接在sql中且不進行jdbc類型轉換,${}可以接受簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是value。

2、parameterType和resultype

parameterType:指定輸入參數類型,mybatis通過ognl從輸入對象中獲取參數值拼接在sql中。

resultType:指定類型的對象。如果有多條數據,則分別進行映射,並把對象放到容器List中。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM