新建项目

需要 MySQL connector 的依赖:

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

创建数据

CREATE TABLE `user_info` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

编写代码

public class MyBatisTest {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://172.16.1.130:3306/wzk-mybatis?characterEncoding=utf-8", "hive", "hive@wzk.icu");
            String sql = "SELECT * FROM user_info WHERE username=?";
            statement = connection.prepareStatement(sql);
            statement.setString(1, "wzk");
            resultSet = statement.executeQuery();
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                int age = resultSet.getInt("age");
                System.out.println("id: " + id + ", username: " + username + ", age: " + age);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (resultSet != null) {
                try { resultSet.close(); } catch (Exception e) { e.printStackTrace(); }
            }
            if (statement != null) {
                try { statement.close(); } catch (Exception e) { e.printStackTrace(); }
            }
            if (connection != null) {
                try { connection.close(); } catch (Exception e) { e.printStackTrace(); }
            }
        }
    }
}

测试运行

输出结果:

id: 1, username: wzk, age: 18
Process finished with exit code 0

问题总结

使用传统 Java 与 JDBC 进行数据库开发存在以下缺点和问题:

代码复杂性和冗余性

  • 手动管理连接:开发者需要手动管理数据库连接,容易出现连接泄漏
  • 重复的代码:执行 SQL 查询需要重复编写大量相似代码
  • 异常处理冗长:每次操作都需要处理 SQLException

缺乏灵活性

  • SQL 硬编码:SQL 语句直接嵌入 Java 代码,导致业务逻辑耦合紧密
  • 数据库依赖性强:不同数据库 SQL 语法差异影响可移植性

事务管理困难

  • 开发者需要手动管理事务的提交和回滚
  • JDBC 无法处理跨多个数据库的分布式事务

性能优化难度大

  • 缺乏连接池支持
  • 无法缓存查询结果

安全性问题

  • 易受 SQL 注入攻击
  • 敏感数据泄露风险

开发效率低

  • 需要了解大量底层细节
  • 代码难以复用和扩展

调试和维护困难

  • 错误定位难
  • 日志支持弱

解决方案

  • Spring JDBC Template:简化 JDBC 开发
  • ORM 框架:如 Hibernate、MyBatis
  • 连接池技术:如 HikariCP
  • 框架事务管理

自定义框架设计

使用端

核心配置文件:

  • sqlMapConfig.xml:存放数据库连接信息,引入 mapper.xml
  • mapper.xml:SQL 语句配置信息

框架端

读取配置

  • Configuration:存放数据库信息、Map<标识, Mapper>
  • MappedStatement:SQL 语句、Statement 类型、输入/输出参数 Java 类型

解析配置

创建 SqlSessionFactoryBuilder 类,使用 dom4j 解析配置文件

SqlSessionFactory

方法:openSession(),获取 sqlSession 接口实现类实例

SqlSession 接口及实现类

封装 CRUD 方法:

  • selectList - 查询所有
  • selectOne - 查询单个

设计模式

  • Builder 设计模式
  • 工厂模式
  • 代理模式