• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • MyBatis學習筆記(一)

    1 、對原生態jdbc程序中問題總結

    jdbc編程步驟: 
    1、 加載數據庫驅動 
    2、 創建并獲取數據庫鏈接 
    3、 創建jdbc statement對象 
    4、 設置sql語句 
    5、 設置sql語句中的參數(使用preparedStatement) 
    6、 通過statement執行sql并獲取結果 
    7、 對sql執行結果進行解析處理 
    8、 釋放資源(resultSet、preparedstatement、connection)

    public static void main(String[] args) {
            // 數據庫連接
            Connection connection = null;
            // 預編譯的Statement,使用預編譯的Statement提高數據庫性能
            PreparedStatement preparedStatement = null;
            // 結果集
            ResultSet resultSet = null;
    
            try {
                // 加載數據庫驅動
                Class.forName("com.mysql.jdbc.Driver");
                // 通過驅動管理類獲取數據庫鏈接
                connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?charactorEncoding=utf-8",
                        "root", "root");
                // 定義sql語句?表示占位符
                String sql = "select * from user where username=?";
                // 獲取預編譯處理statement
                preparedStatement = connection.prepareStatement(sql);
                // 設置參數,第一個參數為sql語句中參數的序號(從1開始),第二個參數為設置的參數值
                preparedStatement.setString(1, "王五");
                // 向數據庫發出sql執行查詢,查詢出結果集
                resultSet = preparedStatement.executeQuery();
                // 遍歷查詢結果集
                while (resultSet.next()) {
                    System.out.println(resultSet.getString("id") + " " + resultSet.getString("username"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 釋放資源
                if (resultSet != null) {
                    try {
                        resultSet.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if (preparedStatement != null) {
                    try {
                        preparedStatement.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    • 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
    • 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

    jdbc問題總結: 
    1.數據庫連接,使用時就創建,不使用立即釋放,對數據庫進行頻繁連接開啟和關閉,造成數據庫資源浪費,影響 數據庫性能。 
    設想:使用數據庫連接池管理數據庫連接。 
    2、將sql語句硬編碼到Java代碼中,如果sql 語句修改,需要重新編譯java代碼,不利于系統維護。 
    設想:將sql語句配置在xml配置文件中,即使sql變化,不需要對java代碼進行重新編譯。 
    3、向preparedStatement中設置參數,對占位符號位置和設置參數值,硬編碼在java代碼中,不利于系統維護。 
    設想:將sql語句及占位符號和參數全部配置在xml中。 
    4、從resutSet中遍歷結果集數據時,存在硬編碼,將獲取表的字段進行硬編碼,,不利于系統維護。 
    設想:將查詢的結果集,自動映射成java對象。

    2、mybatis框架

    MyBatis 本是apache的一個開源項目iBatis 
    2010年這個項目由apache software foundation 遷移到了google code 
    再后來托管到github下(https://github.com/mybatis/mybatis-3/releases)

    MyBatis是一個優秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,使開發者只需要關注 SQL 本身。

    Mybatis通過xml或注解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,并通過java對象和statement中的sql進行映射生成最終執行的sql語句,最后由mybatis框架執行sql并將結果映射成java對象并返回。

    這里寫圖片描述

    3、入門程序示例

    3.1 需求

    根據用戶id(主鍵)查詢用戶信息 
    根據用戶名稱模糊查詢用戶信息 
    添加用戶 
    刪除 用戶 
    更新用戶

    3.2 環境

    mybatis運行環境(jar包): 
    https://github.com/mybatis/mybatis-3/releases下載,3.2.7版本 
    這里寫圖片描述 
    lib下:mybatis依賴包 
    mybatis-3.2.7.jar:核心包 
    mybatis-3.2.7.pdf,操作指南

    另需:MySQL的驅動包

    3.3 工程結構

    這里寫圖片描述

    3.4 log4j.properties配置

    mybatis默認使用log4j作為輸出日志信息。 
    在開發環境下日志級別要設置成DEBUG,生產環境設置成info或error

    # Global logging configuration
    log4j.rootLogger=DEBUG, stdout
    # Console output...
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.5 SqlMapConfig.xml

    SqlMapConfig.xml是mybatis核心配置文件,配置mybatis的數據源、事務管理。

    <?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="development">
            <environment id="development">
            <!-- 使用jdbc事務管理-->
                <transactionManager type="JDBC" />
            <!-- 數據庫連接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver" />
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                    <property name="username" value="root" />
                    <property name="password" value="root" />
                </dataSource>
            </environment>
        </environments>
    </configuration>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3.6 根據用戶id(主鍵)查詢用戶信息

    3.6.1 創建PO類

    Po類作為mybatis進行sql映射使用,po類通常與數據庫表對應,User.java如下:

    Public class User {
        private int id;
        private String username;// 用戶姓名
        private String sex;// 性別
        private Date birthday;// 生日
        private String address;// 地址
    get/set……
    toString……
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.6.2 映射文件

    映射文件命名: 
    User.xml(原始ibatis命名) 
    mapper代理開發映射文件名稱叫XXXMapper.xml,比如:UserMapper.xml、ItemsMapper.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">
    
    <!-- namespace命名空間,用于隔離sql語句,對sql進行分類化管理
     -->
    <mapper namespace="test">
        <!-- 在映射文件中配置很多sql語句 -->
    
        <!-- 通過select執行數據庫查詢
             id:標識 映射文件中的sql
                    將SQL語句封裝到mapperStatement對象中,所以將id稱為statement的id
    
             parameterType:指定輸入參數類型,mybatis通過ognl從輸入對象中獲取參數值拼接在sql中。
             #{}表示一個占位符號,可以有效防止sql注入,可以接收簡單類型值或pojo屬性值。 如果parameterType傳輸單個簡單類型值,#{}括號中可以是value或其它名稱。
             ${}表示拼接sql串,通過${}可以將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換, ${}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是value。
    
             resultType:指定輸出結果單條記錄的類型,mybatis將sql查詢結果的一行記錄數據映射為resultType指定類型的對象。
         -->
    
         <!-- 通過id查詢用戶表的記錄 -->
         <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
            SELECT * FROM USER WHERE id=#{id}
         </select>
    </mapper>
    • 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
    • 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

    3.6.3 在SqlMapConfig.xml中加載映射文件

    在< configuration>< /configuration>標簽下添加

        <!-- 加載映射文件 -->
        <mappers>
            <mapper resource="sqlmap/User.xml"/>
        </mappers>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    3.6.4 程序編寫

    //根據ID查詢用戶信息,得到一個記錄
        @Test
        public void findUserByIdTest(){
    
            //mybatis配置文件
            String resource="SqlMapconfig.xml";
            SqlSession sqlSession=null;
            try {
                //得到配置文件流
                InputStream inputStream = Resources.getResourceAsStream(resource);
    
                //創建會話工廠,傳入mybatis的配置文件信息
                SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
    
                //通過工廠得到SqlSession
                sqlSession=sqlSessionFactory.openSession();
    
                //通過SqlSession操作數據庫,selectOne查詢一條記錄,selectList可以查詢一條或多條記錄。
                //第一個參數:映射文件中statement的id,(namespace.statement的id)
                //第二個參數:傳入sql語句的參數值(必須為映射文件中parameterType指定的類型)
                //返回結果為映射文件中resultType指定類型的對象
                User user=sqlSession.selectOne("test.findUserById",1);
    
                System.out.println(user);
    
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                //釋放資源
                if(sqlSession!=null){
                    sqlSession.close();
                }
            }
        }
    • 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
    • 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

    3.7 根據用戶名稱模糊查詢用戶信息

    User.xml 映射文件增加

    <!-- ${}表示拼接sql串,通過${}可以將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換, ${}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是value。 
        可能引起SQL注入,所以不建議使用
    -->
     <!-- 根據用戶名模糊查詢用戶信息 -->
         <select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
            select * from user where username like '%${value}%'
         </select>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    // 根據用戶名稱模糊查詢用戶列表
        @Test
        public void findUserByNameTest() {
            // mybatis配置文件
            String resource = "SqlMapconfig.xml";
            SqlSession sqlSession = null;
            try {
                // 得到配置文件流
                InputStream inputStream = Resources.getResourceAsStream(resource);
    
                // 創建會話工廠,傳入mybatis的配置文件信息
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
                // 通過工廠得到SqlSession
                sqlSession = sqlSessionFactory.openSession();
    
                // 通過SqlSession操作數據庫,selectOne查詢一條記錄,selectList可以查詢一條或多條記錄。
                List<User> userlist = sqlSession.selectList("test.findUserByName", "小明");
    
                System.out.println(userlist);
    
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 釋放資源
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
        }
    • 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
    • 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

    3.8 添加用戶

    3.8.1 代碼

    User.xml 映射文件增加

         <!-- 添加用戶
         parameterType:指定輸入參數類型是pojo(Plain Ordinary Java Object)簡單的Java對象
         #{}中指定pojo的屬性名,接收到pojo對象的屬性值,mybatis通過ognl獲取對象的屬性值
         user.id 為自增字段,不用寫
          -->
          <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
            insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
          </insert>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
        //添加用戶信息
        @Test
        public void insertUserTest() {
            // mybatis配置文件
            String resource = "SqlMapconfig.xml";
            SqlSession sqlSession = null;
            try {
                // 得到配置文件流
                InputStream inputStream = Resources.getResourceAsStream(resource);
    
                // 創建會話工廠,傳入mybatis的配置文件信息
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
                // 通過工廠得到SqlSession
                sqlSession = sqlSessionFactory.openSession();
    
                //插入用戶對象
                User user=new User();
                user.setUsername("王小軍");
                user.setBirthday(new Date());
                user.setSex("1");
                user.setAddress("洛陽");
    
                // 通過SqlSession操作數據庫
                sqlSession.insert("test.insertUser", user);
    
                //提交事務
                sqlSession.commit();
    
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 釋放資源
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
        }
    • 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
    • 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

    3.8.2 自增主鍵返回

    通過修改sql映射文件,可以將mysql自增主鍵返回: 
    添加selectKey實現將主鍵返回 
    keyProperty:返回的主鍵存儲在pojo中的哪個屬性 
    order:selectKey的執行順序,是相對與insert語句來說,由于mysql的自增原理執行完insert語句之后才將主鍵生成,所以這里selectKey的執行順序為after 
    resultType:返回的主鍵是什么類型 
    LAST_INSERT_ID():是mysql的函數,返回auto_increment自增列新記錄id值。

          <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
            <!--將插入數據的主鍵返回 -->
            <selectKey keyProperty="id" order="AFTER" resultType="java.long.Integer">
                select LAST_INSERT_ID()
            </selectKey>
            insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
          </insert>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.8.3 非自增主鍵返回 (使用uuid())

    使用mysql的uuid()函數生成主鍵,需要修改表中id字段類型為string,長度設置成35位。

    執行思路: 
    先通過uuid()查詢到主鍵,將主鍵輸入 到sql語句中。

    執行uuid()語句順序相對于insert語句之前執行。

        <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
            <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
                select uuid()
            </selectKey>
            insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
        </insert>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    通過Oracle的序列生成主鍵:

        <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
            <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
                SELECT 序列名.nextval()
            </selectKey>
            insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
        </insert>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.9 刪除用戶

         <!-- 根據id刪除用戶-->
         <delete id="deleteUser" parameterType="java.lang.Integer">
            delete from user where id=#{id}
         </delete>
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4
        // 根據id刪除用戶信息
        @Test
        public void deleteUserTest() {
            // mybatis配置文件
            String resource = "SqlMapconfig.xml";
            SqlSession sqlSession = null;
            try {
                // 得到配置文件流
                InputStream inputStream = Resources.getResourceAsStream(resource);
    
                // 創建會話工廠,傳入mybatis的配置文件信息
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
                // 通過工廠得到SqlSession
                sqlSession = sqlSessionFactory.openSession();
    
                // 通過SqlSession操作數據庫
                sqlSession.delete("test.deleteUser", 28);
    
                // 提交事務
                sqlSession.commit();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 釋放資源
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
        }
    • 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
    • 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

    3.10 更新用戶

          <!-- 更新用戶,User中id不能為空-->
         <delete id="updateUser" parameterType="cn.itcast.mybatis.po.User">
            update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
         </delete>
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4
        //更新用戶信息
            @Test
            public void updateUserTest() {
                // mybatis配置文件
                String resource = "SqlMapconfig.xml";
                SqlSession sqlSession = null;
                try {
                    // 得到配置文件流
                    InputStream inputStream = Resources.getResourceAsStream(resource);
    
                    // 創建會話工廠,傳入mybatis的配置文件信息
                    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
                    // 通過工廠得到SqlSession
                    sqlSession = sqlSessionFactory.openSession();
    
                    //更新用戶對象
                    User user=new User();
                    user.setId(27);
                    user.setUsername("王大軍");
                    user.setBirthday(new Date());
                    user.setSex("2");
                    user.setAddress("洛陽");
    
                    // 通過SqlSession操作數據庫
                    sqlSession.insert("test.updateUser", user);
    
                    //提交事務
                    sqlSession.commit();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    // 釋放資源
                    if (sqlSession != null) {
                        sqlSession.close();
                    }
                }
            }
    • 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
    • 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

    3.11 mybatis和Hibernate區別

    mybatis:不完全是一個ORM(Object Relational Mapping,對象關系映射)框架,需要程序員自己編寫Sql語句,不過mybatis可以通過XML或注解方式靈活配置要運行的sql語句,并將java對象和sql語句映射生成最終執行的sql,最后將sql執行的結果再映射生成java對象。 
    可嚴格控制sql執行性能,靈活度高,靈活的前提是mybatis無法做到數據庫無關性,如果需要實現支持多種數據庫的軟件則需要自定義多套sql映射文件,工作量大。 
    適合對關系數據模型要求不高的軟件開發,例如互聯網軟件、企業運營類軟件等,因為這類軟件需求變化頻繁,一但需求變化要求成果輸出迅速。

    hibernate對象/關系映射能力強,數據庫無關性好。學習門檻高,對sql語句進行優化、修改比較困難的,而且怎么設計O/R映射,在性能和對象模型之間如何權衡,以及怎樣用好Hibernate需要具有很強的經驗和能力才行。 
    適用與關系模型要求高的軟件(例如需求固定的定制化軟件),比如:后臺管理系統,erp、orm、oa。

    4、mybatis開發dao的方法

    4.1 需求

    將下邊的功能實現Dao: 
    根據用戶id查詢一個用戶信息 
    根據用戶名稱模糊查詢用戶信息列表 
    添加用戶信息

    4.2 SqlSession的使用范圍

    SqlSession中封裝了對數據庫的操作,如:查詢、插入、更新、刪除等。 
    通過SqlSessionFactory創建SqlSession,而SqlSessionFactory是通過SqlSessionFactoryBuilder進行創建。

    4.2.1 SqlSessionFactoryBuilder

    SqlSessionFactoryBuilder用于創建SqlSessionFacoty,SqlSessionFacoty一旦創建完成就不需要SqlSessionFactoryBuilder了,可以將SqlSessionFactoryBuilder當成一個工具類使用,最佳使用范圍是方法范圍即方法體內局部變量

    4.2.2 SqlSessionFactory

    SqlSessionFactory是一個接口,接口中定義了openSession的不同重載方法,SqlSessionFactory的最佳使用范圍是整個應用運行期間,一旦創建后可以重復使用,通常以單例模式管理SqlSessionFactory。

    4.2.3 SqlSession

    SqlSession是一個面向用戶的接口, sqlSession中定義了數據庫操作,默認使用DefaultSqlSession實現類。

    執行過程如下: 
    1、 加載數據源等配置信息 
    Environment environment = configuration.getEnvironment(); 
    2、 創建數據庫鏈接 
    3、 創建事務對象 
    4、 創建Executor,SqlSession所有操作都是通過Executor完成 
    5、 SqlSession的實現類即DefaultSqlSession,此對象中對操作數據庫實質上用的是Executor

    結論: 
    每個線程都應該有它自己的SqlSession實例。SqlSession的實例不能共享使用,它也是線程不安全的。因此最佳的范圍是請求或方法范圍。絕對不能將SqlSession實例的引用放在一個類的靜態字段或實例字段中。 
    打開一個 SqlSession;使用完畢就要關閉它。通常把這個關閉操作放到 finally 塊中以確保每次都能執行關閉。如下:

    SqlSession session = sqlSessionFactory.openSession();
        try {
             // do work
        } finally {
            session.close();
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.3 原始Dao開發方式

    原始Dao開發方法需要程序員編寫Dao接口和Dao實現類。

    4.3.1 映射文件

    <?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="test">
        <!-- 在映射文件中配置很多sql語句 -->
    
        <!-- 通過id查詢用戶表的記錄 -->
        <select id="findUserById" parameterType="int"
            resultType="cn.itcast.mybatis.po.User">
            SELECT * FROM USER WHERE id=#{value}
        </select>
    
        <select id="findUserByName" parameterType="java.lang.String"
            resultType="cn.itcast.mybatis.po.User">
            select * from user where username like '%${value}%'
        </select>
    
        <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
            <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
                select LAST_INSERT_ID()
            </selectKey>
            insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
        </insert>
    
         <!-- 根據id刪除用戶-->
         <delete id="deleteUser" parameterType="java.lang.Integer">
            delete from user where id=#{id}
         </delete>
    
          <!-- 更新用戶,User中id不能為空-->
         <delete id="updateUser" parameterType="cn.itcast.mybatis.po.User">
            update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
         </delete>
    
    </mapper>
    • 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
    • 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

    4.3.2 Dao接口

    public interface UserDao {
    
        //根據id查詢用戶信息
        public User findUserById(int id) throws Exception;
    
        //添加用戶信息
        public void insertUser(User user) throws Exception;
    
        //刪除用戶信息
        public void deleteUser(int id) throws Exception;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.3.3 Dao實現

    public class UserDaoImpl implements UserDao{
    
        //需要向dao實現類注入SqlSessionFactory
        //這里通過構造方法注入
        private SqlSessionFactory sqlSessionFactory;
        public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
            this.sqlSessionFactory=sqlSessionFactory;
        }
    
        @Override
        public User findUserById(int id) throws Exception {
            SqlSession sqlSession=sqlSessionFactory.openSession();
            User user=null;
            try{
                user=sqlSession.selectOne("test.findUserById",id);
            }finally{
                sqlSession.close();//釋放資源
            }
            return user;
        }
    
        @Override
        public void insertUser(User user) throws Exception {
            SqlSession sqlSession=sqlSessionFactory.openSession();
            sqlSession.insert("test.insertUser",user);//執行插入操作
            sqlSession.commit();//提交事務
            sqlSession.close();//釋放資源
        }
    
        @Override
        public void deleteUser(int id) throws Exception {
            SqlSession sqlSession=sqlSessionFactory.openSession();
            sqlSession.delete("test.deleteUser",id);//執行插入操作
            sqlSession.commit();//提交事務
            sqlSession.close();//釋放資源
        }
    
    }
    
    • 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
    • 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

    4.3.4 測試

    public class UserDaoImplTest {
        private SqlSessionFactory sqlSessionFactory;
    
        @Before
        public void setUp() throws Exception {
            //mybatis配置文件
            String resource="SqlMapConfig.xml";
            //得到配置文件流
            InputStream inputStream=Resources.getResourceAsStream(resource);
            //創建回話工廠,傳入mybatis的配置文件信息
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 
        }
    
        @Test
        public void testFindUserById() throws Exception {
            //創建UserDao的對象
            UserDao userDao=new UserDaoImpl(sqlSessionFactory);
    
            //調用UserDao的方法
            User user=userDao.findUserById(1);
    
            System.out.println(user);
        }
    
    }
    • 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
    • 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

    原始Dao開發中存在以下問題:

    Dao方法體存在重復代碼:通過SqlSessionFactory創建SqlSession,調用SqlSession的數據庫操作方法 
    調用sqlSession的數據庫操作方法需要指定statement的id,這里存在硬編碼,不得于開發維護。 
    調用sqlsession方法時傳入的變量,由于sqlsession方法使用泛型< Object>,即使變量類型傳入錯誤,在編譯階段也不報錯,不利于程序員開發。

    4.4 Mapper動態代理方式

    4.4.1 實現原理

    Mapper接口開發方法只需要程序員編寫Mapper接口(相當于Dao接口),由Mybatis框架根據接口定義創建接口的動態代理對象,代理對象的方法體同上邊Dao接口實現類方法。
    

    Mapper接口開發需要遵循以下規范: 
    1、 Mapper.xml(本程序用UserMapper.xml)文件中的namespace與mapper接口的類路徑相同。

    <mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
    • 1
    • 1

    2、 Mapper接口方法名和Mapper.xml中定義的每個statement的id相同 
    3、 Mapper接口方法的輸入參數類型和mapper.xml中定義的每個sql 的parameterType的類型相同 
    4、 Mapper接口方法的輸出參數類型和mapper.xml中定義的每個sql的resultType的類型相同

        <select id="findUserById" parameterType="int"
            resultType="cn.itcast.mybatis.po.User">
            SELECT * FROM USER WHERE id=#{value}
        </select>
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4
    package cn.itcast.mybatis.mapper;
    public interface UserMapper {   
        //根據id查詢用戶信息
        public User findUserById(int id) throws Exception; 
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    4.4.2 加載UserMapper.xml文件

    修改SqlMapConfig.xml文件:

      <!-- 加載映射文件 -->
      <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
      </mappers>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    4.4.3 測試

    public class UserMapperTest {
        private SqlSessionFactory sqlSessionFactory;
    
        @Before
        public void setUp() throws Exception {
            //mybatis配置文件
            String resource="SqlMapConfig.xml";
            //得到配置文件流
            InputStream inputStream=Resources.getResourceAsStream(resource);
            //創建回話工廠,傳入mybatis的配置文件信息
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 
        }
    
        @Test
        public void testFindUserById() throws Exception {
            //獲取session
            SqlSession sqlsession=sqlSessionFactory.openSession();
            //獲取mapper接口的代理對象
            UserMapper userMapper=sqlsession.getMapper(UserMapper.class);
            //調用代理對象方法
            User user=userMapper.findUserById(1);
            System.out.println(user);
            sqlsession.close();
        }
    
    }
    • 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
    • 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

    4.4.4 總結

    selectOne和selectList 
    動態代理對象調用sqlSession.selectOne()和sqlSession.selectList()是根據mapper接口方法的返回值決定,如果返回list則調用selectList方法,如果返回單個對象則調用selectOne方法。

    namespace 
    mybatis官方推薦使用mapper代理方法開發mapper接口,程序員不用編寫mapper接口實現類,使用mapper代理方法時,輸入參數可以使用pojo包裝對象或map對象,保證dao的通用性。 
    注意:持久層方法的參數可以使用pojo、map等,service方法中建議不要使用包裝類型(不利于業務層的可擴展)

    5、SqlMapConfig.xml

    SqlMapConfig.xml中配置的內容和順序如下:

    properties(屬性)
    settings(全局配置參數)
    typeAliases(類型別名)
    typeHandlers(類型處理器)
    objectFactory(對象工廠)
    plugins(插件)
    environments(環境集合屬性對象)
        environment(環境子屬性對象)
             transactionManager(事務管理)
             dataSource(數據源)
    mappers(映射器)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5.1 properties(屬性)

    在classpath下定義db.properties文件

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis
    jdbc.username=root
    jdbc.password=root
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    SqlMapConfig.xml引用如下:

        <!--加載屬性文件  -->
        <properties resource="db.properties"></properties>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC" />
                <dataSource type="POOLED">
                    <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>
            </environment>
        </environments>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意: MyBatis 將按照下面的順序來加載屬性:

    ? 在 properties 元素體內定義的屬性首先被讀取。 
    ? 然后會讀取properties 元素中resource或 url 加載的屬性,它會覆蓋已讀取的同名屬性。 
    ? 最后讀取parameterType傳遞的屬性,它會覆蓋已讀取的同名屬性。

    因此,通過parameterType傳遞的屬性具有最高優先級,resource或 url 加載的屬性次之,最低優先級的是 properties 元素體內定義的屬性。

    建議:在properties文件中定義屬性名要有一定的特殊性,如:XXX.XXX.XX,以防止被parameterType傳遞的同名屬性無意覆蓋。

    5.2 settings全局參數配置

    mybatis全局配置參數,全局參數將會影響mybatis的運行行為。 
    這里寫圖片描述

    5.3 ctypeAliases(別名)重點

    在mapper.xml中,定義很多的statement,statement需要parameterType指定輸入參數的類型、需要resultType指定輸出結果的映射類型。

    如果在指定類型時輸入類型全路徑,不方便進行開發,可以針對parameterType或resultType指定的類型定義一些別名,在mapper.xml中通過別名定義,方便開發。

    5.3.1 mybatis默認支持別名

     別名        映射的類型
    _byte       byte 
    _long       long 
    _short      short 
    _int        int 
    _integer    int 
    _double     double 
    _float      float 
    _boolean    boolean 
    string      String 
    byte        Byte 
    long        Long 
    short       Short 
    int         Integer 
    integer     Integer 
    double      Double 
    float       Float 
    boolean     Boolean 
    date        Date 
    decimal     BigDecimal 
    bigdecimal  BigDecimal 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    5.3.2 自定義別名

    在SqlMapConfig.xml中配置:

    <typeAliases>
        <!-- 單個別名定義 -->
        <typeAlias type="cn.itcast.mybatis.po.User" alias="user"/>
        <!-- 批量別名定義,掃描整個包下的類,別名為類名(首字母大寫或小寫都可以) -->
        <package name="cn.itcast.mybatis.po"/>
        <package name="其它包"/>
    </typeAliases>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5.4 typeHandlers(類型處理器)

    每當MyBatis 設置參數到PreparedStatement 或者從ResultSet 結果集中取得值時,就會使用typeHandler 來處理數據庫類型與java 類型之間轉換。

    <select id="findUserById" parameterType="int" resultType="user">
            select * from user where id = #{id}
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    下表描述了默認的typeHandlers: 
    這里寫圖片描述

    對于用戶自定義的類型,創建一個自定義的類型處理器。參考:http://blog.csdn.net/huey2672/article/details/38151607

    5.5 mappers(映射器)

    使用相對于類路徑的資源
    如:<mapper resource="sqlmap/User.xml" />
    
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
    使用完全限定路徑
    如:<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />
    
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
    使用mapper接口類路徑
    如:<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>
    
    注意:此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5
    注冊指定包下的所有mapper接口
    如:<package name="cn.itcast.mybatis.mapper"/>
    注意:此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中。
    
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    6、輸入映射

    6.1 #{}與${}

    #{}實現的是向prepareStatement中的預處理語句中設置參數值,sql語句中#{}表示一個占位符即?。 
    使用占位符#{}可以有效防止sql注入 
    在使用時不需要關心參數值的類型,mybatis會自動進行java類型和jdbc類型的轉換。 
    #{}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,#{}括號中可以是value或其它名稱。

    ${}和#{}不同,通過${}可以將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換 
    ${}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是value。 
    使用${}不能防止sql注入,但是有時用${}會非常方便

    6.2 傳遞pojo對象

    Mybatis使用ognl表達式解析對象字段的值,如下例子:

    <!—傳遞pojo對象綜合查詢用戶信息 -->
        <select id="findUserByUser" parameterType="user" resultType="user">
           select * from user where id=#{id} and username like '%${username}%'
        </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    6.3 傳遞pojo包裝對象

    開發中通過pojo傳遞查詢條件 ,查詢條件是綜合的查詢條件,不僅包括用戶查詢條件還包括其它的查詢條件(比如將用戶購買商品信息也作為查詢條件),這時可以使用包裝對象傳遞輸入參數。

    6.3.1 定義包裝類型pojo

    在包裝類型的pojo中將復雜的查詢條件包裝進去。

    public class UserQueryVo {//在這里包裝所需要的查詢條件
    
        //用戶查詢條件
        private UserCustom userCustom;
        //還可以包裝其他的查詢條件,訂單,商品等 
    
        public UserCustom getUserCustom() {
            return userCustom;
        }
    
        public void setUserCustom(UserCustom userCustom) {
            this.userCustom = userCustom;
        }
    
        //其他條件的getter、setter
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    6.3.2 mapper.xml

    在UserMapper.xml中定義用戶信息綜合查詢

        <!--用戶信息綜合查詢  -->
        <select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo" resultType="cn.itcast.mybatis.po.UserCustom">
            select * from user where user.sex=#{userCustom.sex} and user.username like '%${userCustom.username}%'
        </select>
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    6.3.3 mapper.java

    UserMapper.java 接口類中

        //用戶信息的綜合查詢
        public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;
    • 1
    • 2
    • 1
    • 2

    6.3.4 測試代碼

    UserMapperTest.java

    // 用戶信息的綜合查詢
        @Test
        public void testFindUserList() throws Exception {
            // 獲取session
            SqlSession sqlsession = sqlSessionFactory.openSession();
            // 獲取mapper接口的代理對象
            UserMapper userMapper = sqlsession.getMapper(UserMapper.class);
    
            //創建包裝對象,設置查詢條件
            UserQueryVo userQueryVo=new UserQueryVo();
            UserCustom userCustom=new UserCustom();
            userCustom.setSex("1");
            userCustom.setUsername("張");
            userQueryVo.setUserCustom(userCustom);
    
            List<UserCustom> list=userMapper.findUserList(userQueryVo);
    
            System.out.println(list);
            sqlsession.close();
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    6.4 傳遞hashmap

    Sql映射文件定義如下:

    <!-- 傳遞hashmap綜合查詢用戶信息 -->
        <select id="findUserByHashmap" parameterType="hashmap" resultType="user">
           select * from user where id=#{id} and username like '%${username}%'
        </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    id和username是hashmap的key

    異常測試: 
    傳遞的map中的key和sql中解析的key不一致。 
    測試結果沒有報錯,只是通過key獲取值為空。

    7、輸出映射

    7.1 resultType

    可輸出簡單類型、pojo對象、pojo列表、hashmap

    使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。 
    如果查詢出來的列名和pojo中的屬性名全部不一致,沒有創建pojo對象。 
    只要查詢出來的列名和pojo中的屬性有一個一致,就會創建pojo對象,其他屬性為相應類型的默認值。

    輸出pojo對象和輸出pojo列表在sql中定義的resultType是一樣的。

    返回單個pojo對象要保證sql查詢出來的結果集為單條,內部使用session.selectOne方法調用,mapper接口使用pojo對象作為方法返回值。 
    返回pojo列表表示查詢出來的結果集可能為多條,內部使用session.selectList方法,mapper接口使用List對象作為方法返回值。

    輸出pojo對象可以改用hashmap輸出類型,將輸出的字段名稱作為map的key,value為字段值。

    7.2 resultMap

    resultType可以指定pojo將查詢結果映射為pojo,但需要pojo的屬性名和sql查詢的列名一致方可映射成功。
    如果sql查詢字段名和pojo的屬性名不一致,可以通過resultMap將字段名和屬性名作一個對應關系 ,resultMap實質上還需要將查詢結果映射到pojo對象中。
    resultMap可以實現將查詢結果映射為復雜類型的pojo,比如在查詢結果映射對象中包括pojo和list實現一對一查詢和一對多查詢。
    

    7.2.1 定義reusltMap和statement

    UserMapper.xml

        <!--定義resultMap -->
        <!-- type:resultMap最終映射的java對象類型,可以使用別名
              id:對此resultMap的標識
         -->
        <resultMap type="User" id="userResultMap">
            <!-- id表示查詢結果集中唯一標識 
                 column:查詢出來的列名
                 property:type指定的pojo類型中對應的屬性名
            -->
            <id column="id_" property="id"/>
            <!-- result:查詢結果中普通列名 -->
            <result column="username_" property="username"/>
        </resultMap>
    
        <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
            select id id_,username username_ from user where id=#{value}
        </select>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    UserMapper.java接口

        //根據id查詢用戶信息,使用resultMap輸出
        public User findUserByIdResultMap(int id) throws Exception;
    • 1
    • 2
    • 1
    • 2

    8、動態SQL(重點)

    8.1 if 和 where

        <!-- 用戶信息綜合查詢總數-->
        <select id="findUserCount" parameterType="cn.itcast.mybatis.po.UserQueryVo" resultType="int">
            select count(*) from user
            <!-- where可以自動去掉條件中的第一個and -->
            <where>
                <if test="userCustom!=null">
                    <if test="userCustom.sex!=null and userCustom.sex!=''">
                        and user.sex=#{userCustom.sex}
                    </if>
                    <if test="userCustom.username!=null and userCustom.username!=''">
                        and user.username like '%${userCustom.username}%'
                    </if>
                </if>
            </where>
        </select>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    8.2 foreach

    8.2.1 通過pojo傳遞list

    在pojo中定義list屬性ids存儲多個用戶id,并添加getter/setter方法

    public class UserQueryVo {//在這里包裝所需要的查詢條件
    
        //用戶查詢條件
        private UserCustom userCustom;
    
        //傳遞多個用戶id
        private List<Integer> ids;、
    //getter/setter...
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    UserMapper.xml

        <select id="findUsersByIds" parameterType="cn.itcast.mybatis.po.UserQueryVo"  resultType="cn.itcast.mybatis.po.UserCustom">
            SELECT * FROM USER 
            <where>
            <if test="ids!=null and ids.size>0">
                <foreach collection="ids" item="id" open=" and id in("  close=")"  separator="," >
                    #{id}
                </foreach>
            </if>
            </where>
        </select>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Mapper接口

    public List<UserCustom> findUsersByIds(UserQueryVo userQueryVo) throws Exception;
    • 1
    • 1

    測試代碼

        @Test
        public void findUsersByIds() throws Exception {
            // 獲取session
            SqlSession sqlsession = sqlSessionFactory.openSession();
            // 獲取mapper接口的代理對象
            UserMapper userMapper = sqlsession.getMapper(UserMapper.class);
    
            List<Integer> ids=new ArrayList<Integer>();
            ids.add(1);
            ids.add(10);
            UserQueryVo userQueryVo=new UserQueryVo();
            userQueryVo.setIds(ids);
            List<UserCustom> list=userMapper.findUsersByIds(userQueryVo);
            System.out.println(list);
            sqlsession.close();
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    8.2.2 傳遞單個List

    傳遞List類型在編寫mapper.xml沒有區別,唯一不同的是只有一個List參數時它的參數名為list。

    UserMapper.xml

        <select id="findUserByList" parameterType="java.util.List" resultType="cn.itcast.mybatis.po.UserCustom">
            select * from user 
            <where>
            <!-- 傳遞List,List中是pojo -->
            <if test="list!=null">
                <foreach collection="list" item="item" open="and id in(" close=")" separator=",">
                   #{item.id} 
                </foreach>
            </if>
            </where>
        </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Mapper接口

    public List<UserCustom> findUserByList(List userlist) throws Exception;
    • 1
    • 1

    測試代碼

        @Test
        public void findUserByList()throws Exception{
            //獲取session
            SqlSession session = sqlSessionFactory.openSession();
            //獲限mapper接口實例
            UserMapper userMapper = session.getMapper(UserMapper.class);
    
            //構造查詢條件List
            List<User> userlist = new ArrayList<User>();
            User user = new User();
            user.setId(1);
            userlist.add(user);
            user = new User();
            user.setId(2);
            userlist.add(user); 
    
            //傳遞userlist列表查詢用戶列表
            List<UserCustom>list = userMapper.findUserByList(userlist);
            //關閉session
            session.close();
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    8.2.3 傳遞單個數組(數組中是pojo)

    <!-- 傳遞數組綜合查詢用戶信息 -->
        <select id="selectUserByArray" parameterType="Object[]" resultType="user">
            select * from user 
            <where>
            <!-- 傳遞數組 -->
            <if test="array!=null">
            <foreach collection="array" index="index" item="item" open="and id in("separator=","close=")">
                #{item.id} 
            </foreach>
            </if>
            </where>
        </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    sql只接收一個數組參數,這時sql解析參數的名稱mybatis固定為array,如果數組是通過一個pojo傳遞到sql則參數的名稱為pojo中的屬性名。

    index:為數組的下標。 
    item:為數組每個元素的名稱,名稱隨意定義 
    open:循環開始 
    close:循環結束 
    separator:中間分隔輸出

    8.2.4 傳遞單個數組(數組中是字符串類型)

    <!-- 傳遞數組綜合查詢用戶信息 -->
        <select id="selectUserByArray" parameterType="Object[]" resultType="user">
            select * from user 
            <where>
            <!-- 傳遞數組 -->
            <if test="array!=null">
            <foreach collection="array" index="index" item="item" open="and id in(" separator="," close=")">
                #{item} 
            </foreach>
            </if>
            </where>
        </select>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    如果數組中是簡單類型則寫為#{item},不用再通過ognl獲取對象屬性值了。

    8.3 sql片段

    Sql中可將重復的sql提取出來,使用時用include引用即可,最終達到sql重用的目的,如下:

    <!-- 傳遞pojo綜合查詢用戶信息 -->
        <select id="findUserList" parameterType="user" resultType="user">
            select * from user 
            <where>
            <if test="id!=null and id!=''">
            and id=#{id}
            </if>
            <if test="username!=null and username!=''">
            and username like '%${username}%'
            </if>
            </where>
        </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    將where條件抽取出來:

    <sql id="query_user_where">
        <if test="id!=null and id!=''">
            and id=#{id}
        </if>
        <if test="username!=null and username!=''">
            and username like '%${username}%'
        </if>
    </sql>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    使用include引用:

    <select id="findUserList" parameterType="user" resultType="user">
            select * from user 
            <where>
            <include refid="query_user_where"/>
            </where>
    </select>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意:如果引用其它mapper.xml的sql片段,則在引用時需要加上namespace,如下: 

    版權聲明:本文為w405722907原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/w405722907/article/details/72386926

    智能推薦

    Mybatis學習筆記(一)

    1、環境描述 java版本:1.8 開發工具:idea 2018版 mysql:8.x版本 mybatis:3.4.6版本 lombok mybatis 在開發中最為關鍵的是其 SqlSession 的使用和 mapper 文件的配置。 本文將圍繞它來介紹Mybatis的入門案例。 2、項目結構 2.1 配置文件 在 idea 中,使用maven項目。在 resources 資源文件夾中創建文件夾...

    MyBatis學習筆記(一)

    一、MyBatis介紹   MyBatis 是一款優秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記...

    Mybatis學習筆記一

    Mybatis學習筆記一 概述 Mybatis 是一個優秀的基于 java 的持久層框架,它內部封裝了 jdbc,使開發者只需要關注 sql 語句本身,而不需要花費精力去處理加載驅動、創建連接、創建 statement 等繁雜的過程。 mybatis 通過 xml 或注解的方式將要執行的各種 statement 配置起來,并通過 java 對象和 statement 中sql 的動態參數進行映射生...

    MyBatis學習筆記(一)

    1 、對原生態jdbc程序中問題總結 jdbc編程步驟:  1、 加載數據庫驅動  2、 創建并獲取數據庫鏈接  3、 創建jdbc statement對象  4、 設置sql語句  5、 設置sql語句中的參數(使用preparedStatement)  6、 通過statement執行sql并獲取結果  7、 對sql執行結...

    Mybatis學習筆記(一)

    嗷嗷 環境統一 JDK1.8 Mysql5.7 maven3.6.1 簡介 什么是mybatis MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,并且改名為MyBatis 。2013年11月遷移到Github。 iBATIS一詞來源于“internet”和...

    猜你喜歡

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    精品国产乱码久久久久久蜜桃不卡