1. 原始 JDBC 是什么样的 ?

简单的梳理一下我们使用 JDBC 的流程:① 引入相关数据库驱动 Jar 包 ② 创建一个数据库连接类
在这个类中包括:数据库驱动的加载、数据库连接的配置、连接对象的获取、以及释放关闭,以及具体的SQL以及其执行语句,下面是一个
下面代码是 JDBC最原始的方式,没有经过任何优化和封装,功能是查询student表中的所有记录

  1. package cn.ideal.jdbc;
  2. import cn.ideal.domain.Student;
  3. import java.sql.*;
  4. public class JdbcDemo {
  5. public static void main(String[] args) {
  6. Connection connection = null;
  7. Statement statement = null;
  8. ResultSet resultSet = null;
  9. try {
  10. // 注册驱动
  11. Class.forName("com.mysql.jdbc.Driver");
  12. // 获取与数据库的连接对象
  13. connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "root99");
  14. // 定义sql语句
  15. String sql = "SELECT * FROM student";
  16. // 获取执行sql语句的对象statement
  17. statement = connection.createStatement();
  18. // 执行sql语句,获取结果集
  19. resultSet = statement.executeQuery(sql);
  20. // 遍历获取到的结果集
  21. while (resultSet.next()) {
  22. int id = resultSet.getInt(1);
  23. String name = resultSet.getString(2);
  24. Double score = resultSet.getDouble(3);
  25. Student student = new Student();
  26. student.setId(id);
  27. student.setName(name);
  28. student.setScore(score);
  29. System.out.println(student.toString());
  30. }
  31. } catch (ClassNotFoundException e) {
  32. e.printStackTrace();
  33. } catch (SQLException e) {
  34. e.printStackTrace();
  35. } finally {
  36. // 释放资源,后调用的先释放
  37. if (resultSet != null) {
  38. try {
  39. resultSet.close();
  40. } catch (SQLException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. if (statement != null) {
  45. try {
  46. statement.close();
  47. } catch (SQLException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. if (connection != null) {
  52. try {
  53. connection.close();
  54. } catch (SQLException e) {
  55. e.printStackTrace();
  56. }
  57. }
  58. }
  59. }
  60. }

通过这段代码我们可以分析到:

  1. 代码中,数据库驱动名称、链接地址、账号密码等,全部被写死到程序中,也就是说当你需要修改某些值时,你必须要修改源代码,这也就是我们所谓的 “硬编码”
    1. 举个例子:如果我们更换了数据库 Eg:MySQL -> Oracle ,或者更换了服务器,因此地址发生了变化,又或者数据库密码被修改,我们就都需要回到源代码中进行修改,重新编译、打包上线
  2. 数据库连接需要频繁的创建和释放,系统资源浪费,且影响性性能(数据库连接池技术解决)

这段代码是使用了 preparedStatement 预处理对象进行替代其父类 Statement 对象,这也是我们只考虑原始 JDBC 情况下 一般会选用的,那么它又有什么问题呢?

  1. // 定义sql
  2. String sql = "SELECT * FROM user WHERE username = ? AND password = ?";
  3. // 获取执行sql的对象
  4. preparedStatement = connection.prepareStatement(sql);
  5. // 给?赋值
  6. preparedStatement.setString(1, username);
  7. preparedStatement.setString(2, password);
  8. // 执行查询
  9. resultSet = preparedStatement.executeQuery();
  1. 当使用 preparedStatement 设置占位符语句,并且对其进行参数传递时都是 “硬编码“ 因为 sql 语句的 where 条件可能会变化,如果修改 sql 还需要,修改源代码

还有一种情况是这样的:

  1. // 遍历获取到的结果集
  2. while (resultSet.next()) {
  3. int id = resultSet.getInt("id");
  4. String name = resultSet.getString("name");
  5. Double score = resultSet.getDouble("score");
  6. Student student = new Student();
  7. student.setId(id);
  8. student.setName(name);
  9. student.setScore(score);
  10. }
  1. 如果我们在 ResultSet 中遍历结果集时如果我们使用 getInt 等这种方法,参数为字段名,当数据库对应表字段出现改变时,源代码再一次需要被修改

之前我们一定程度上的便捷我们的开发,可能有使用过 Spring 的 JdbcTemplate 或者 Apache 的 DBUtils ,它们都是对 JDBC 的简单封装,只能算作工具类,不能算作一个完整的框架, 而我们下面要讲的 Mybatis 则是一个可能解决这些问题的框架

2. MyBatis 概述

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录 ——百度百科

  1. MyBatis 可以将 sql 语句配置在 XML 中,这样解决了 sql 语句写在 Java类中的 “硬编码” 问题
  2. 通过输入参数映射机制,将参数灵活的配置起来,解决了在 Java 类中手工配置的问题
  3. 通过输出映射机制, 结果集的检索自动映射成相应的 Java对象,避免了 JDBC 中对结果集的手工检索
  4. 这种映射机制实际上使用了 ORM 的思想
    • ORM (Object Relational Mapping) 对象关系映射
    • 简单理解:数据库表和实体类中的属性进行对应,我们可以操作实体类就实现操作数据库表

      3. MyBatis 的环境配置(IDEA)

      3.1 创建 Maven项目

      打开 IDEA ,创建一个 Maven 项目,如下图所示
      12.1-01-001.png
      修改 GroupId 和 ArtifactId 的值
  • GroupID是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构
    • 一般以域名倒序填写
  • ArtifactID就是项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称

12.1-01-002.png
设置其地址
12.1-01-003.png

3.2 修改 pom 导入MyBatis坐标

选择打包方式为 jar包: <packaging>jar</packaging>
下面我们导入了 mybatis、mysql、log4j (日志)、junit (单元测试) 的依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>cn.ideal</groupId>
  7. <artifactId>code_01_EnvironmentSetup</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <!-- 打包方式 -->
  10. <packaging>jar</packaging>
  11. <!-- 对应依赖 -->
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.mybatis</groupId>
  15. <artifactId>mybatis</artifactId>
  16. <version>3.4.5</version>
  17. </dependency>
  18. <dependency>
  19. <groupId>mysql</groupId>
  20. <artifactId>mysql-connector-java</artifactId>
  21. <version>5.1.6</version>
  22. </dependency>
  23. <dependency>
  24. <groupId>log4j</groupId>
  25. <artifactId>log4j</artifactId>
  26. <version>1.2.12</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>junit</groupId>
  30. <artifactId>junit</artifactId>
  31. <version>4.10</version>
  32. </dependency>
  33. </dependencies>
  34. </project>

3.3 创建实体类

package cn.ideal.domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    private Integer id;
    private String username;
    private Integer telephone;
    private Date birthday;
    private String gender;
    private String address;

    ...为节省长度,省略其对应 get set方法,请大家自行补充

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", telephone=" + telephone +
                ", birthday=" + birthday +
                ", gender='" + gender + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

3.4 创建mapper接口

mapper 与我们之前学习的 dao 的意义是一致的,只是名称上的不同,对应的 mapper 写为 dao 也是可以的

package cn.ideal.mapper;

import cn.ideal.domain.User;
import java.util.List;

public interface UserMapper {
    /**
     * 查询所有用户信息
     * @return
     */
    List<User> findAllUserInfo();
}

3.5 编写数据库连接池配置文件(主配置文件)

在resources下创建一个名为 SqlMapConfig.xml 的文件,这也就是我们的主配置文件
而数据库连接池的配置,是配置环境中重要的一点

  1. 由于其配置文件为 xml 格式,我们需要在头部指定 xml 的版本和编码信息

    <?xml version="1.0" encoding="UTF-8"?>
    
  2. 为了保证 MyBatis 在读取该 xml 文件时,配置文件中的每一个标签对,以及标签对中的参数值配置符合标准,引入 DTD 规范约束

    <!DOCTYPE configuration
         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-config.dtd">
    

    接下来就是配置正文,

  • <environments></environments>标签中的 default 值与 <environment></<environment> 中的 id 值务必保持一致
  • <transactionManager></transactionManager>配置 Mybatis 的事务控制类型
  • <dataSource></<dataSource> 配置数据库连接信息
    • <property></property> 配置具体的值
  • 在底部的 <mappers></mappers>标签中指定了映射配置文件的位置,也就是说我们 SQL相关的语句都在这个指定的配置文件中,而这里我们指定了它的路径

详细代码:

<?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">
<!-- mybatis 主配置文件 -->
<configuration>
    <!-- 配置环境,和spring整合后 environments配置将会被废除 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用JDBC事务管理 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ideal_mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="=root99"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 指定映射配置文件的位置 -->
    <mappers>
        <mapper resource="cn.ideal.mapper/UserMapper.xml"/>
    </mappers>
</configuration>

3.6 SQL映射配置文件

为了解决 原生 JDBC 的一些不足,在 MyBatis 中,SQL语句不会直接出现在 Java类中,它将几乎所有的 SQL 语句放在 配置文件中,他会在适当的情况下,加载这个配置文件,完成一定的操作
首先仍然是,xml的版本和编码格式,然后引入DTD约束
然后在 <mapper></mapper> 标签中编写我们具体的配置

  • 其中的 namespace属性,就是对SQL进行分类化管理,将实现不同业务的SQL分开,这里我们对其取值就是我们之前mapper接口的全限定类
  • 特别注意:创建包时,我们创建的是一个三级目录,而创建配置文件的目录的时候,直接创建 cn.ideal.mapper 是一级目录,我们需要一层一层的创建,保证其也为三级目录
  • <mapper></mapper>标签中创建一个 <select></select> 标签 其中 属性 id 的值为mapper接口的方法名
  • parameterType、parameterMap、resultType、resultClass、resultMap分别代表
  • 输入参数类型、输入参数集合、结果类型、结果类、结果集合
    <?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">
    <mapper namespace="cn.ideal.mapper.UserMapper">
      <select id="findAllUserInfo" resultType="cn.ideal.domain.User">
          select * from  user
      </select>
    </mapper>
    
    总结:到这里Mybatis的简单认识以及环境的搭建就说完了,篇幅问题,关于Mybatis 分成几篇来讲,感谢大家的支持