JavaWeb进阶之路:MyBatis初体验

JavaWeb进阶之路:MyBatis初体验

1. 简介

1.1 什么是MyBatis

在这里插入图片描述

  • MyBatis 是一款优秀的持久层框架。
  • 它支持自定义 SQL、存储过程以及高级映射。
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

1.2 如何获得MyBatis?

  • Maven仓库:https://mvnrepository.com/artifact/org.mybatis/mybatis
  • GitHub:https://github.com/mybatis/mybatis-3
  • 官网:https://mybatis.org/mybatis-3/zh/index.html

1.3 什么是持久化?

  • 即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。

  • 将程序数据在持久状态和瞬时状态间转换的机制。

1.4 什么是持久层?

  • 完成持久化的代码块。
  • 界限十分明显。Dao层、Service层、Controller层。

1.5 为什么要用MyBatis?

  • 帮助开发者更方便的将数据存入数据库中。
  • 简化JDBC的代码,自动化。
  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql。
  • 使用的人多!

2. 第一个MyBatis程序

2.1 搭建环境

  1. 搭建数据库
    # 创建数据库
    CREATE DATABASE `mybatis`;
    # 使用数据库
    USE `mybatis`;
    # 创建表
    CREATE TABLE `user` (
    	`id` INT ( 10 ) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    	`name` VARCHAR ( 40 ) DEFAULT NULL,
    	`password` VARCHAR ( 40 ) DEFAULT NULL 
    ) ENGINE = INNODB CHARSET = utf8;
    # 插入数据
    INSERT INTO `user`
    VALUES
    	( 1, '梁大侠', '123123' ),
    	( 2, '张三', '654321' ),
    	( 3, '李四', '123456' );
    
  2. 新建项目
    1. 新建一个普通的Maven项目。

    2. 将项目下的src文件夹删除,让此项目变为一个父工程。

    JavaWeb进阶之路:MyBatis初体验_第1张图片

    1. 导入依赖

      
      
      <dependency>
          <groupId>mysqlgroupId>
          <artifactId>mysql-connector-javaartifactId>
          <version>8.0.25version>
      dependency>
      
      
      <dependency>
          <groupId>org.mybatisgroupId>
          <artifactId>mybatisartifactId>
          <version>3.5.7version>
      dependency>
      
      
      <dependency>
          <groupId>org.junit.jupitergroupId>
          <artifactId>junit-jupiter-apiartifactId>
          <version>5.8.0-M1version>
          <scope>testscope>
      dependency>
      

2.2 配置MyBatis

  1. 新建一个MyBatis-01的模块:

    JavaWeb进阶之路:MyBatis初体验_第2张图片

  2. 创建配置文件:

    在模块目录 src/main/resources 下创建一个名为 mybatis-config.xml 文件。

    
    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">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC"/>
                    
                    <property name="username" value="root"/>
                    
                    <property name="password" value="123456"/>
                dataSource>
            environment>
        environments>
    configuration>
    

    注意:在xml中,&需要进行转义,否则会出错。

    第二种方法,不推荐使用:

    JavaWeb进阶之路:MyBatis初体验_第3张图片

  3. 编写MyBatisUtils类

    util 包下创建 MybatisUtils 工具类。

    package com.lmx.demo.util;
    
    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 java.io.IOException;
    import java.io.InputStream;
    
    public class MybatisUtils {
    
        private static SqlSessionFactory sqlSessionFactory;
    
        static {
            try {
                /**
                 * 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。
                 * SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。
                 * 而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
                 */
                String resource = "mybatis-config.xml";
                // MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易。
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获得SqlSession
         *
         * SqlSession:相当于jdbc中的Connection,提供了在数据库执行 SQL 命令所需的所有方法。
         * 你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
         * @return SqlSession
         */
        public static SqlSession getSqlSession() {
            return sqlSessionFactory.openSession();
        }
    
    }
    
    类名 作用域和生命周期
    SqlSessionFactoryBuilder 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。
    SqlSessionFactory SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
    SqlSession 每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。

2.3 编写代码

  1. 编写实体类

    在模块下创建一个名为 pojo 的包,在 pojo 包下创建 User 实体类。这里通过 lombok 实现有参、无参构造方法、 get 和 set 方法还有 toString方法。

    package com.lmx.demo.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
    
      private long id;
      private String name;
      private String password;
    
    }
    

    lombok的基本用法:https://www.jianshu.com/p/2543c71a8e45

  2. 编写Mapper接口

    在模块下新建一个包 mapper ,这里的 mapper 等同于我们以前创建的包 dao ,在 mapper 下新建一个 UserMapper 接口。

    package com.lmx.demo.mapper;
    
    import com.lmx.demo.pojo.User;
    
    import java.util.List;
    
    /**
     * 这里相当于UserDao
     */
    public interface UserMapper {
    
        List<User> getUserList();
    
    }
    
  3. 编写Mapper.xml配置文件

    mapper 包下新建一个名为 UserMapper.xml xml文件。

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.lmx.demo.mapper.UserMapper">
        
        <select id="getUserList" resultType="com.lmx.demo.pojo.User">
            
            select * from user
        select>
    mapper>
    

    命名空间的作用有两个,一个是利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。

    以上步骤操作完后,有个非常重要的一步,就是在我们的 mybatis-config.xml 文件中,注册 mapper

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        
        <environments default="development">
            .....
        environments>
    
        <mappers>
            
            <mapper resource="com/lmx/demo/mapper/UserMapper.xml"/>
        mappers>
    configuration>
    

2.4 运行查看结果

  1. 创建测试类

    在模块 src/test/java 目录下新建一个和 main 目录一样的包结构。在 mapper 包下新建一个名为 UserMapperTest 测试类。

    package com.lmx.demo.mapper;
    
    import com.lmx.demo.pojo.User;
    import com.lmx.demo.util.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.jupiter.api.Test;
    
    import java.util.List;
    
    public class UserMapperTest {
    
        @Test
        public void getUserListTest() {
            /**
             * SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
             * 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。
             * 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。
             */
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            // 通过sqlSession实现接口UserMapper,相当于jdbc中的 UserDao的实现类
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            // 调用接口查询
            List<User> userList = userMapper.getUserList();
            // 打印输出结果
            System.out.println(userList);
            // 因为不能被共享,所每次执行完都要关闭 SqlSession
            sqlSession.close();
        }
    
    }
    

    此时运行会出现一个报错:java.lang.ExceptionInInitializerError 我们看到报错内容,告诉我们找不到 UserMapper.xml 资源。引发这个问题的原因是因为 maven 项目无法导出在 resource 目录外的资源文件。

    JavaWeb进阶之路:MyBatis初体验_第4张图片

  2. 解决问题

    遇到这种问题的解决方案有2种:

    1. maven 默认的资源文件都是放在 resource 目录下的。 我们需要手动的去配置 maven 资源文件过滤,在我们的父工程的 pom.xml 中的 build 配置资源过滤。

       <build>
           <resources>
               <resource>
                   <directory>src/main/resourcesdirectory>
                   <includes>
                       <include>**/*.xmlinclude>
                       <include>**/*.propertiesinclude>
                   includes>
                   <filtering>falsefiltering>
               resource>
               <resource>
                   <directory>src/main/javadirectory>
                   <includes>
                       <include>**/*.xmlinclude>
                       <include>**/*.propertiesinclude>
                   includes>
                   <filtering>falsefiltering>
               resource>
           resources>
      build>
      
    2. 将我们 main/java/com.xxx.xxx/mapper 下的 UserMapper.xml 移动到 resources 目录下。再修改 mybatis-config.xml 中的 mapper 路径即可。

      JavaWeb进阶之路:MyBatis初体验_第5张图片

  3. 运行结果

    JavaWeb进阶之路:MyBatis初体验_第6张图片
    可以看到,我们的数据从数据库获取到并且打印出来了。

你可能感兴趣的:(我的JavaWeb开发之旅,java,mybatis,数据库)