【MyBatis_00】使用JDBC操作数据库

79 阅读5分钟
  • 一辈子很长、要去做一些浪漫的事。去看一些风景、读一些书、培养一两个爱好。

最近学习了MyBatis的源码教程【书籍<< 手写mybatis:渐进式源码实践 >>】、本着把知识从输入转为输出的心态,打算按照如下的过程整理一下相关知识。

  • 使用JDBC操作数据库
  • MyBatis框架基础使用教程
  • 结合参考书籍提供的mini版本的MyBatis、分析这一部分的实现以及对应的源码框架。这一部分会给出方法级别的图示,超级详细。

其中第一部分就一篇文章、主要用于回顾一下JDBC相关操作,解释为什么使用MyBatis框架。

第二部分主要内容为mybatis相关框架的使用、会使用大量示例代码。

第三部分主要就是借助参考书籍 <<手写mybatis渐进式源码实践>> 以及其他源码相关书籍去分析MyBatis的源码。会给出详细的注释以及图示。

本文主要内容就是回顾一下JDBC的相关操作。主要内容有

  • 使用JDBC操作数据库步骤
  • StatementPrepareStatement的区别

JDBC操作数据库步骤

不管做什么事、首先第一步就是和目标建立连接、因此使用JDBC操作数据库也是、引入相关依赖。

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.32</version>
</dependency>

第一步:注册数据库驱动、获取数据库连接

public class JdbcUtils {
​
    private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
    private static final String URL = "jdbc:mysql://localhost:3306/master";
    private static final String USER = "root";
    private static final String PASSWORD = "root123!";
​
    private static final Logger logger = LoggerFactory.getLogger(JdbcUtils.class);
​
    public static Connection getConnection() {
        try {
            Class.forName(DRIVER);
            return DriverManager.getConnection(URL, USER, PASSWORD);
        } catch (ClassNotFoundException | SQLException e) {
            logger.error("数据库连接失败");
            throw new RuntimeException(e);
        }
    }
    
}

通过Class.forName()注册数据库驱动、通过DriverManager获取数据连接。这样我们的程序就和MySQL数据库建立起连接了。

00_jdbc_connect.png

第二步:通过获取的连接创建Statement或者PrepareStatement对象,后者对前者进行了扩展,推荐使用后者主要原因有以下几点:

StatementPrepareStatement
参数设置字符串拼接、会有sql注入的风险通过占位符、自动绑定参数
性能每一次执行时都会重新编译编译后缓存,适合重复执行相同的 SQL
安全性容易受到 SQL 注入攻击容易受到 SQL 注入攻击

PrepareStatement:会预编SQL,这是指的在数据库层面、以MySQL为例、预编译过程如下:

# 1.执行预编译语句
prepare selectUser from 'select * from user where user_name like ?';
#2.设置变量,例如:
set @username='%小明%'; 
#3.执行语句,例如:
execute selectUser using @username;

一般使用PrepareStatement对象进行数据库操作,可以采用如下的方式获取:

String sql = "insert into user(user_name,password) values(?,?)";
PreparedStatement statement = connection.prepareStatement(sql);

第三步参数设置:

statement.setString(1, "晚风也很温柔_123");
statement.setString(2, "123456");

相反如果使用Statement对象

Statement statement = connection.createStatement();
String sql = "insert into user(user_name,password) values("+"晚风也很温柔_123"+"123456"+")";

SQL就需要我们进行手动拼接、如果代码"有毒",则会造成极大的生产事故。比如如下的SQL语句:

String sql = "insert into user(user_name,password) values("+"晚风也很温柔_123"+"123456"+");" +
        "delete FROM user where 1=1;";

第四步执行SQL语句:

statement.execute();
int updateCount = statement.getUpdateCount();
// 如果执行的是查询操作就可以通过如下的方式获取值、并装配到JavaBean中去。
ResultSet resultSet = statement.getResultSet();
while (resultSet.next()) {
    System.out.println(resultSet.getString("user_name"));
}

到这里就可以把数据库的记录封装为JavaBean对象,也就把数据从数据库中加载到我们的Java应用中了。

上面只是一个简单的插入方法示例,当我们需要编写多个方法时,可以看到很多的步骤都是重复操作的,具体的步骤如下:

  • 注册驱动
  • 获取链接【重复操作】
  • 编辑sql
  • 参数设置
  • 执行sql【重复操作】
  • 获取返回结果【重复操作】

重复的操作往往可以优化、因此这就是我们使用MyBatis的优点之一,上述重复的操作都不需要我们手动编码,只需要正确填写配置文件之后,编写mapper文件中的sql语句即可。极大的简化了我们的编码、提高了开发速度。

使用MyBatis操作数据库

引入MyBatisMaven坐标如下:

<!--mysql -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.32</version>
</dependency>
<!--mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.16</version>
</dependency>
<!--单元测试 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.9</version>
    <scope>test</scope>
</dependency>

编写主配置文件mybatis-config-datasource.xml:配置、数据库连接、缓存、插件、Mapper等信息。

<?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>
​
    <settings>
        <!-- 全局缓存:true/false -->
        <setting name="cacheEnabled" value="true"/>
        <!--缓存级别:SESSION/STATEMENT-->
        <setting name="localCacheScope" value="STATEMENT"/>
    </settings>
​
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="root123!"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- Mapper.XML 配置 -->
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

主配置文件和UserMapper.xml的位置关系:

01_mybatis_resource.png

编写IUserMapper接口以及对应的Mapper文件:

public interface IUserMapper {
    SysUser getUserById(Integer id);
} 
​

他们之间的关系以及文件含义放在下一篇文章详细说明:

  • namespace: 指向接口的全限定名称
  • id:和接口的方法名称一致相对应即可
<?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="com.supersist.mybatis.tutorial.mapper.IUserMapper">
    <select id="getUserById" resultType="com.supersist.mybatis.tutorial.pojo.SysUser">
        select * from user where id = #{id}
    </select>
</mapper>

实体类:

public class SysUser{
    private Integer id;
​
    private String userName;
  // 省略get、set方法
}

使用:

// 加载配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config-datasource.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
// 获取mapper
IUserMapper mapper = sqlSession.getMapper(IUserMapper.class);
// 调用相关方法
SysUser user = mapper.getUserById(1);
System.out.println(user);
​

通过上述两个对比,很明显mybatis对数据库的操作比纯jdbc的操作要简单得多,缺点就是需要学习一下相关的知识、才能正确使用MyBatis

下一章:<< 【MyBatis_01】第一个MyBatis程序 >>