• Java精进-手写持久层框架


    前言

    本文适合有一定java基础的同学,通过自定义持久层框架,可以更加清楚常用的mybatis等开源框架的原理。

    JDBC操作回顾及问题分析

    学习java的同学一定避免不了接触过jdbc,让我们来回顾下初学时期接触的jdbc操作吧

    以下代码连接数据库查询用户表信息,用户表字段分别为用户id,用户名username。

    1. Connection connection = null;
    2. PreparedStatement preparedStatement = null;
    3. ResultSet resultSet = null;
    4. User user = new User();
    5. try {
    6. // 加载数据库驱动
    7. //Class.forName("com.mysql.jdbc.Driver");
    8. Class.forName("com.mysql.cj.jdbc.Driver");
    9. // 通过驱动管理类获取数据库链接
    10. connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "mimashi3124");
    11. // 定义sql语句?表示占位符
    12. String sql = "select * from user where username = ?";
    13. // 获取预处理statement
    14. preparedStatement = connection.prepareStatement(sql);
    15. // 设置参数,第⼀个参数为sql语句中参数的序号(从1开始),第⼆个参数为设置的参数值
    16. preparedStatement.setString(1, "盖伦");
    17. // 向数据库发出sql执⾏查询,查询出结果集
    18. resultSet = preparedStatement.executeQuery();
    19. // 遍历查询结果集
    20. while (resultSet.next()) {
    21. int id = resultSet.getInt("id");
    22. String username = resultSet.getString("username");
    23. // 封装User
    24. user.setId(id);
    25. user.setUsername(username);
    26. }
    27. System.out.println(user);
    28. } catch (
    29. Exception e) {
    30. e.printStackTrace();
    31. } finally {
    32. // 释放资源
    33. if (resultSet != null) {
    34. try {
    35. resultSet.close();
    36. } catch (SQLException e) {
    37. e.printStackTrace();
    38. }
    39. }
    40. if (preparedStatement != null) {
    41. try {
    42. preparedStatement.close();
    43. } catch (SQLException e) {
    44. e.printStackTrace();
    45. }
    46. }
    47. if (connection != null) {
    48. try {
    49. connection.close();
    50. } catch (SQLException e) {
    51. e.printStackTrace();
    52. }
    53. }
    54. }

    查看代码我们可以发现使用JDBC操作数据库存在以下问题:

    1. 数据库连接创建、释放频繁造成系统资源浪费,从⽽影响系统性能。
    2. Sql语句我们是写在代码里的,代码不容易维护,实际应⽤中sql变化的可能较⼤,sql变动需要改变 java代码。
    3. 使⽤preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不⼀定,可能多也可能少,修改sql还要修改代码,系统不易维护。
    4. 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据 库记录封装成pojo对象解析⽐较⽅便

    问题解决思路

    1. 使⽤数据库连接池初始化连接资源,避免资源浪费
    2. 将sql语句抽取到xml配置中,这种sql的变动只用关注xml文件,不比去一堆java代码里改写sql
    3. 参数硬编码问题可以使用反射、内省等技术、自动将实体与表字段进行映射。

    自己动手写个持久层框架

    接下来,我们来一个个解决上面的问题

    数据库连接池我们可以直接使用c3p0提供的ComboPooledDataSource即可

    为了解决sql硬编码问题,我们要把sql写到xml文件中,那自然是要定义一个xml文件了。

    光有sql肯定不行,毕竟我们要先连接数据库,sql语句才有存在的意义。所以xml中得先定义数据配置信息,然后才是sql语句。

    1.定义配置xml文件

    我们新建一个sqlMapConfig.xml,定义数据源信息、并且增加两个sql语句,parameterType为sql执行参数,resultType为方法返回实体。

    代码如下(数据库不同版本使用驱动类可能不同):

    1. "driverClass" value="com.mysql.cj.jdbc.Driver"/>
    2. "jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai"/>
    3. "username" value="root"/>
    4. "password" value="mimashi3124"/>

    现在xml文件数据库信息也有了,sql语句定义也有了,还有什么问题呢?

    我们实际中对sql的操作会涉及到不同的表,所以我们改进一下,把每个表的sql语句单独放在一个xml里,这样结构更清晰就容易维护。

    优化以后的xml配置现在是这样了

    1. sqlMapConfig.xml
    2. "driverClass" value="com.mysql.cj.jdbc.Driver"/>
    3. "jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai"/>
    4. "username" value="root"/>
    5. "password" value="mimashi3124"/>
    6. "mapper.xml">
     
    

    mapper

  • 相关阅读:
    大数据面试题:Spark和MapReduce之间的区别?各自优缺点?
    基于GoogleNet深度学习网络的花朵类型识别matlab仿真
    Oracle数据库 sql优化
    pandas读取csv数据、使用set_index函数把多个数据列转化为多层行索引(keys参数指定需要被转化的多个数据列列表、形成多层行索引)
    云原生加速器企业维格表创始人陈霈霖:提供人人可用的数字化转型全新方案,真正驱动组织创新
    excel高级绘图技巧100讲(二十三)-Excel中实现倒计时计数
    牛客网《剑指offer》专栏刷题练习之掌握动态规划思想
    由于找不到msvcp120.dll 无法继续执行怎么解决(最新方法分享)
    Android设置TabLayout熟悉及下划线宽度
    A-Level经济真题(5)
  • 原文地址:https://blog.csdn.net/guanshengg/article/details/126436119