java自己动手写框架_自己动手写一个持久层框架

本文分析了JDBC存在的问题,如硬编码、频繁创建链接等,并提出了解决方案,包括配置文件存储、连接池和反射等。接着,作者介绍了自定义持久层框架的设计思路,包括配置文件的加载、解析以及核心组件如Configuration和MappedStatement的作用。同时,文章还讨论了如何创建表和编写测试类。最后,解释了namespace和id在多条SQL和多个Mapper之间的必要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. JDBC问题分析

我们来看一段JDBC的代码:

public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { //1. 加载数据库驱动 Class.forName("com.mysql.jdbc.Drive"); //2. 通过驱动管理类获取数据库链接 connection = DriverManager.getConnection("jdbc:mysql://hocalhost:3306/mybatis?characterEncoding=utf-8", "root","root"); //3. 定义SQL语句 ?表示占位符 String sql = "SELECT * FROM user WHERE username = ?"; //4. 获取预处理对象Statement preparedStatement = connection.prepareStatement(sql); //5. 设置参数,第一个参数为SQL语句中参数的序号(从1开始),第二个参数为设置的参数值 preparedStatement.setString(1,"tom"); //6. 向数据库发出SQL执行查询,查询出结果集 resultSet = preparedStatement.executeQuery(); //7. 遍历查询结果集 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 (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException throwables) { throwables.printStackTrace(); } }

可以看到,直接使用JDBC开发是存在一些问题的,我们来分析下:

问题分析:

数据库配置信息存在硬编码问题

频繁创建、释放数据库链接

//1. 加载数据库驱动Class.forName("com.mysql.jdbc.Drive");//2. 通过驱动管理类获取数据库链接connection = DriverManager.getConnection("jdbc:mysql://hocalhost:3306/mybatis?characterEncoding=utf-8","root","root");

sql语句、设置参数、获取结果集均存在硬编码问题

//3. 定义SQL语句 ?表示占位符String sql = "SELECT * FROM user WHERE username = ?";//4. 获取预处理对象StatementpreparedStatement = connection.prepareStatement(sql);//5. 设置参数,第一个参数为SQL语句中参数的序号(从1开始),第二个参数为设置的参数值 preparedStatement.setString(1,"tom"); //6. 向数据库发出SQL执行查询,查询出结果集 resultSet = preparedStatement.executeQuery(); int id = resultSet.getInt("id"); String userName = resultSet.getString("username");

手动封装返回结果集 较为繁琐

//7. 遍历查询结果集while (resultSet.next()){ int id = resultSet.getInt("id"); String userName = resultSet.getString("username"); //封装User user.setId(id); user.setUserName(userName); } System.out.println(user);

解决思路:

写在配置文件中

连接池(c3p0、dbcp、德鲁伊...)

配置文件 (和1放一起吗? No,经常变动和不经常变动的不要放在一起)

反射、内省

下面根据这个解决思路,自己动手写一个持久层框架,写框架之前分析这个框架需要做什么

2. 自定义框架思路分析

使用端(项目):

引入自定义持久层框架的jar包

提供两部分配置信息:

数据库配置信息

SQL配置信息(SQL语句)

使用配置文件来提供这些信息:

sqlMapConfig.

mapper.

自定义持久层框架(工程):

持久层框架的本质就是对JDBC代码进行了封装

加载配置文件:根据配置文件的路径加载配置文件成字节输入流,存储内存中

创建Resources类 方法:getResourceAsStream(String path)

Q: getResourceAsStearm方法需要执行两次分别加载sqlMapConfig额和mapper吗?

A:可以但没必要,我们可以在sqlMapConfig.

创建两个javaBean:(容器对象):存放的就是配置文件解析出来的内容

Configuration:核心配置类:存放sqlMapConfig.

MappedStatement:映射配置类:存放mapper.

解析配置文件:使用dom4j

创建类:SqlSessionFactoryBuilder 方法:build(InputStream in) 这个流就是刚才存在内存中的

使用dom4j解析配置文件,将解析出来的内容封装到容器对象中

创建SqlSessionFactory对象;生产sqlSession:会话对象(工厂模式 降低耦合,根据不同需求生产不同状态的对象)

创建sqlSessionFactory接口及实现类DefaultSqlSessionFactory

openSession(); 生产sqlSession

创建SqlSession接口及实现类DefaultSession

定义对数据库的CRUD操作,例如:

selectList()

selectOne()

update()

delete()

...

创建Executor接口及实现类SimpleExecutor实现类

query(Configuration con,MappedStatement ms,Object ...param);执行JDBC代码,Object ...param具体的参数值,可变参;

3. 创建表并编写测试类

SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for user-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of user-- ----------------------------INSERT INTO `user` VALUES (1, 'lucy');INSERT INTO `user` VALUES (2, 'tom');INSERT INTO `user` VALUES (3, 'jack');SET FOREIGN_KEY_CHECKS = 1;

1. 创建一个Maven项目—— Ipersistence_test

Q:

为什么要有namespace和id ?

A:

当一个*Mapper.中有多条sql时,无法区分具体是哪一条所以增加 id

如果有UserMapper.和ProductMapper.,假设他们的查询的id都为”selectList“,那么将无法区分具体是查询user还是查询product的。

所以增加 namespace

namespace.id 组成sql的唯一标识,也称为statementId

sqlMapConfig.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值