• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • MyBatis01

    標簽: mybatis  java

    MyBatis01

    1. JDBC編程問題總結

    1.1 數據準備

    /*
    Navicat MySQL Data Transfer
    
    Source Server         : localhost_3306
    Source Server Version : 50521
    Source Host           : localhost:3306
    Source Database       : mybatis
    
    Target Server Type    : MYSQL
    Target Server Version : 50521
    File Encoding         : 65001
    
    Date: 2015-04-09 16:03:53
    */
    
    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for `orders`
    -- ----------------------------
    DROP TABLE IF EXISTS `orders`;
    CREATE TABLE `orders` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `user_id` int(11) NOT NULL COMMENT '下單用戶id',
      `number` varchar(32) NOT NULL COMMENT '訂單號',
      `createtime` datetime NOT NULL COMMENT '創建訂單時間',
      `note` varchar(100) DEFAULT NULL COMMENT '備注',
      PRIMARY KEY (`id`),
      KEY `FK_orders_1` (`user_id`),
      CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of orders
    -- ----------------------------
    INSERT INTO `orders` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
    INSERT INTO `orders` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
    INSERT INTO `orders` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null);
    
    -- ----------------------------
    -- Table structure for `user`
    -- ----------------------------
    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) NOT NULL COMMENT '用戶名稱',
      `birthday` date DEFAULT NULL COMMENT '生日',
      `sex` char(1) DEFAULT NULL COMMENT '性別',
      `address` varchar(256) DEFAULT NULL COMMENT '地址',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of user
    -- ----------------------------
    INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
    INSERT INTO `user` VALUES ('10', '張三', '2014-07-10', '1', '北京市');
    INSERT INTO `user` VALUES ('16', '張小明', null, '1', '河南鄭州');
    INSERT INTO `user` VALUES ('22', '陳小明', null, '1', '河南鄭州');
    INSERT INTO `user` VALUES ('24', '張三豐', null, '1', '河南鄭州');
    INSERT INTO `user` VALUES ('25', '陳小明', null, '1', '河南鄭州');
    INSERT INTO `user` VALUES ('26', '王五', null, null, null);
    

    示例

    1.2 創建工程

    說明:

    • 簡單Java項目即可
    • 可以使用Maven或者Jar的方式添加驅動

    代碼:

    package com.lanou3g;
    
    
    import java.sql.*;
    
    public class Main {
        public static void main(String[] args) {
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
    
            try {
                // 加載數據庫驅動
                Class.forName("com.mysql.cj.jdbc.Driver");
    
                // 通過驅動管理類獲取數據庫鏈接
                connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&characterEncoding=utf-8", "root", "123456");
                // 定義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.3 JDBC問題總結

    1. 數據庫連接創建、釋放頻繁造成系統資源浪費,從而影響系統性能。如果使用數據庫連接池可解決此問題。
    2. Sql語句在代碼中硬編碼,造成代碼不易維護,實際應用中sql變化的可能較大,sql變動需要改變java代碼
    3. 使用preparedStatement向占有位符號傳參數存在硬編碼,因為sql語句的where條件不一定,可能多也可能少,修改sql還要修改代碼,系統不易維護
    4. 對結果集解析存在硬編碼(查詢列名),sql變化導致解析代碼變化,系統不易維護,如果能將數據庫記錄封裝成pojo對象解析比較方便

    2. MyBatis架構

    MyBatis架構圖

    2.1 說明

    • mybatis配置
      • SqlMapConfig.xml: 此文件作為mybatis的全局配置文件,配置了mybatis的運行環境等信息
      • mapper.xml: 即sql映射文件,文件中配置了操作數據庫的sql語句。此文件需要在SqlMapConfig.xml中加載,通常一個表對應一個mapper.xml
    • 通過mybatis環境等配置信息構造SqlSessionFactory即會話工廠
    • 由會話工廠創建sqlSession即會話,操作數據庫需要通過sqlSession進行
    • mybatis底層自定義了Executor執行器接口操作數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器
    • Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sql的id即是Mapped statement的id
    • Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數
    • Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql后將輸出結果映射至java對象中,輸出結果映射過程相當于jdbc編程中對結果的解析處理過程

    3. Mybatis入門程序

    根據用戶ID查詢一個用戶

    3.1 mybatis下載

    mybatis的代碼由github托管,下載地址:https://github.com/mybatis/mybatis-3/releases

    下載

    3.2 添加依賴

    依賴

    3.3 POJO

    User:

    package com.lanou3g.pojo;
    
    import java.io.Serializable;
    import java.util.Date;
    
    public class User implements Serializable {
        private static final long serialVersionUID = 1L;
        private Integer id;
        private String username;// 用戶姓名
        private String sex;// 性別
        private Date birthday;// 生日
        private String address;// 地址
    
    
        public Integer getId() {
            return id;
        }
        public void setId(Integer 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 + "]";
        }
    
    }

    Orders

    package com.lanou3g.pojo;
    
    import java.io.Serializable;
    import java.util.Date;
    
    public class Orders  implements Serializable{
    
        private static final long serialVersionUID = 1L;
    
        private Integer id;
    
        private Integer userId;
    
        private String number;
    
        private Date createTime;
    
        private String note;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public Integer getUserId() {
            return userId;
        }
    
        public void setUserId(Integer userId) {
            this.userId = userId;
        }
    
        public String getNumber() {
            return number;
        }
    
        public void setNumber(String number) {
            this.number = number == null ? null : number.trim();
        }
    
        public Date getCreateTime() {
            return createTime;
        }
    
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
    
        public String getNote() {
            return note;
        }
    
        public void setNote(String note) {
            this.note = note == null ? null : note.trim();
        }
    }

    3.4 配置文件

    mybatis核心配置文件

    在src下創建sqlMapConfig.xml

    <?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>
    
        <environments default="development">
            <environment id="development">
                <!--使用JDBC事務管理-->
                <transactionManager type="JDBC"/>
                <!--數據庫連接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <!--mapper文件的位置-->
        <mappers>
            <mapper resource="com/lanou3g/sqlmap/User.xml"/>
        </mappers>
    </configuration>

    log

    在src下創建log4j.properties

    log4j.rootLogger=DEBUG, stdout
    
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

    說明:
    - 不適用log4j 不會影響mybatis的使用

    mapper映射文件

    在sqlmap包下創建User的映射文件 User.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">
    <!--寫SQL語句
        命名空間: user.findUserById-->
    <mapper namespace="user">
    
        <!--通過ID查詢一個用戶-->
        <select id="findUserById" parameterType="Integer" resultType="com.lanou3g.pojo.User">
            SELECT * FROM USER WHERE id = #{v}
        </select>
    </mapper>

    說明:
    - 在mybatis中使用 #{v} 來作為占位符(?)拼接sql語句
    - id: statement的id或者叫做 sql 的id
    - parameterType: 聲明輸入參數的類型
    - resultType: 聲明輸出結果的類型,應該填寫pojo的全路徑

    3.5 測試運行

    使用Junit來進行測試,編寫測試程序的步驟:
    1. 加載sqlMapConfig.xml配置文件
    2. 通過SqlSessionFactoryBuilder創建SqlSessionFactory對象
    3. 創建SqlSession對象
    4. 使用SqlSession對象執行在mapper中編寫的sql語句獲得返回值
    5. 打印結果
    6. 釋放資源

    package com.lanou3g.junit;
    
    import com.lanou3g.pojo.User;
    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 java.io.InputStream;
    
    public class MybatisFirstTest {
    
        @Test
        public void  testMybatis() throws Exception{
            String resource = "sqlMapConfig.xml";
            InputStream in = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
            SqlSession sqlSession = sqlSessionFactory.openSession();
            User user = sqlSession.selectOne("user.findUserById", 10);
            System.out.println(user);
            in.close();
            sqlSession.close();
        }
    }

    3.5 說明

    sqlMapConfig.xml,User.xml和MybatisFirstTest.java之間的對應關系如圖所示:

    • 在sqlMapConfig.xml的mappers標簽中將所有的map.xml進行注冊,需要制定xml文件的位置
    • 在Java中使用Resource.getResourceAsXXX來加載配置sqlMapConfig.xml,可以有很多的返回值,這個返回值需要和SqlSessionFactoryBuilder.build()方法中的參數對應上
    • 在查找一條數據時使用 selectOne方法,第一個參數是mapper中sql語句的id,這個id是mapper的namespace.id

    3.6 增刪改查入門

    業務需求:
    - 根據用戶名模糊查詢用戶列表
    - 添加用戶
    - 更新用戶
    - 刪除用戶

    1. 模糊查詢

    映射

    <select id="findUserByUserName" parameterType="String" resultType="com.lanou3g.pojo.User">
        SELECT * FROM USER WHERE username LIKE '%${value}%'
    </select>

    測試代碼:

    @Test
    public void testFindUserByName() throws Exception {
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> users =
                sqlSession.selectList("user.findUserByUserName", "五");
        for (User user : users) {
            System.out.println(user);
        }
        in.close();
        sqlSession.close();
    }

    效果:

    說明
    #{}${}

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

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

    mapper還可以寫成:

    <select id="findUserByUserName" parameterType="String" resultType="com.lanou3g.pojo.User">
        SELECT * FROM USER WHERE username LIKE "%"#{value}"%"
    </select>

    運行結果:

    parameterType和resultType
    • parameterType:指定輸入參數類型,mybatis通過ognl從輸入對象中獲取參數值拼接在sql中
    • resultType:指定輸出結果類型,mybatis將sql查詢結果的一行記錄數據映射為resultType指定類型的對象。如果有多條數據,則分別進行映射,并把對象放到容器List中
    selectOne和selectList
    • selectOne: 查詢一條記錄,如果使用selectOne查詢多條記錄則拋出異常
    • selectList: 可以查詢一條或多條記錄

    2. 添加用戶

    映射文件:

    <insert id="saveUser" parameterType="com.lanou3g.pojo.User">
        INSERT INTO `user`
        (username,birthday,sex,address) VALUES
        (#{username},#{birthday},#{sex},#{address})
    </insert>

    java代碼:

    @Test
    public void testSaveUser() throws Exception {
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = new User();
        user.setUsername("張飛");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("蜀國");
        sqlSession.insert("user.saveUser", user);
        System.out.println(user);
        in.close();
        sqlSession.close();
    }

    運行效果

    存在問題:
    當保存完成后User的id并沒有跟數據庫中的值保持一致

    mysql自增主鍵返回

    在mysql中有:

    SELECT LAST_INSERT_ID()

    可以返回上一次增加的主鍵值,修改配置文件:

    <insert id="saveUser" parameterType="com.lanou3g.pojo.User">
        <selectKey keyColumn="id" keyProperty="id" order="AFTER"
                   resultType="int">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO `user`
        (username,birthday,sex,address) VALUES
        (#{username},#{birthday},#{sex},#{address})
    </insert>

    說明:
    - selectKey: 標簽實現主鍵返回
    - keyColumn: 主鍵對應的表中的哪一列
    - keyProperty: 主鍵對應的pojo中的哪一個屬性
    - order: 設置在執行insert語句前執行查詢id的sql,還是在執行insert語句之后執行查詢id的sql
    - resultType: 設置返回的id的類型

    運行結果

    3. 修改用戶

    映射文件

    <update id="updateUserById" parameterType="com.lanou3g.pojo.User">
        UPDATE `user` SET
        username = #{username} WHERE id = #{id}
    </update>

    測試代碼

    @Test
    public void testUpdateUser() throws Exception {
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = new User();
        user.setId(26); // 設置id
        user.setUsername("關羽");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("蜀國");
        sqlSession.update("user.updateUserById", user);
        System.out.println(user);
        sqlSession.commit();
        in.close();
        sqlSession.close();
    }

    運行結果:

    4. 刪除用戶

    配置文件:

    <delete id="deleteById" parameterType="Integer">
        DELETE FROM USER WHERE id = #{VALUE}
    </delete>

    測試代碼:

    @Test
    public void testDelById() throws Exception{
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.delete("user.deleteById", 26);
        sqlSession.commit();
        in.close();
        sqlSession.close();
    }

    運行效果:

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

    智能推薦

    【Mybatis01】實現縮小版銀行轉賬+分頁查詢功能

    一、實現轉賬 1.1 項目實現圖和結構圖 1.1.1 pojo實體類 !分頁查詢表 1.2 全局文件mybatis.xml的編寫 1.3 mapper.xml的編寫(用來進行查詢!!!) 1.3.1分析: (確保轉賬用戶的正確性)因為需要確認轉賬用戶的賬號密碼輸入正確,所以需要根據賬號和密碼進行表查詢并且拿出查出來的對象,以作后續的余額更改操作! (確保入帳用戶的正確性)同上述,查表,取出對象! ...

    MyBatis(01)

    攔截器和過濾器的區別 1.攔截器是SpringMvc框架的組件,而過濾器是java提供的API 2.攔截器只能攔截目標為DispatcherServlet的請求 過濾器范圍廣,過濾目標可以是任何資源 3.功能上攔截器功能更強,和SpringMvc配合更方便 過濾器只和javaEEAPI相關,功能稍弱 小結 如果實現http協議級別的基本攔截過濾,就使用過濾器 如果實現對SpringMvc控制器代碼...

    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壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

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