🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
前言
本文适合有一定java基础的同学,通过自定义持久层框架,可以更加清楚常用的mybatis等开源框架的原理。
JDBC操作回顾及问题分析
学习java的同学一定避免不了接触过jdbc,让我们来回顾下初学时期接触的jdbc操作吧
以下代码连接数据库查询用户表信息,用户表字段分别为用户id,用户名username。
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
User user = new User();
try {
// 加载数据库驱动
//Class.forName("com.mysql.jdbc.Driver");
Class.forName("com.mysql.cj.jdbc.Driver");
// 通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "mimashi3124");
// 定义sql语句?表示占位符
String sql = "select * from user where username = ?";
// 获取预处理statement
preparedStatement = connection.prepareStatement(sql);
// 设置参数,第⼀个参数为sql语句中参数的序号(从1开始),第⼆个参数为设置的参数值
preparedStatement.setString(1, "盖伦");
// 向数据库发出sql执⾏查询,查询出结果集
resultSet = preparedStatement.executeQuery();
// 遍历查询结果集
while (resultSet.next()) {
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
// 封装User
user.setId(id);
user.setUsername(username);
}
System.out.println(user);
} catch (
Exception e) {
e.printStackTrace();
} finally {
// 释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
查看代码我们可以发现使用JDBC操作数据库存在以下问题:
- 数据库连接创建、释放频繁造成系统资源浪费,从⽽影响系统性能。
- Sql语句我们是写在代码里的,代码不容易维护,实际应⽤中sql变化的可能较⼤,sql变动需要改变 java代码。
- 使⽤preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不⼀定,可能多也可能少,修改sql还要修改代码,系统不易维护。
- 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据 库记录封装成pojo对象解析⽐较⽅便
问题解决思路
- 使⽤数据库连接池初始化连接资源,避免资源浪费
- 将sql语句抽取到xml配置中,这种sql的变动只用关注xml文件,不比去一堆java代码里改写sql
- 参数硬编码问题可以使用反射、内省等技术、自动将实体与表字段进行映射。
自己动手写个持久层框架
接下来,我们来一个个解决上面的问题
数据库连接池我们可以直接使用c3p0提供的ComboPooledDataSource即可
为了解决sql硬编码问题,我们要把sql写到xml文件中,那自然是要定义一个xml文件了。
光有sql肯定不行,毕竟我们要先连接数据库,sql语句才有存在的意义。所以xml中得先定义数据配置信息,然后才是sql语句。
1.定义配置xml文件
我们新建一个sqlMapConfig.xml,定义数据源信息、并且增加两个sql语句,parameterType为sql执行参数,resultType为方法返回实体。
代码如下(数据库不同版本使用驱动类可能不同):
<configuration>
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="mimashi3124"/>
<select id="selectOne" parameterType="org.example.pojo.User"
resultType="org.example.pojo.User">
select * from user where id = #{id} and username =#{username}
select>
<select id="selectList" resultType="org.example.pojo.User">
select * from user
select>
configuration>
现在xml文件数据库信息也有了,sql语句定义也有了,还有什么问题呢?
我们实际中对sql的操作会涉及到不