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

我们来看一段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. 获取预处理对象Statement preparedStatement = 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.xml :存放数据库的配置信息

mapper.xml :存放SQL配置信息

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

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

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

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

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

A:可以但没必要,我们可以在sqlMapConfig.xml中写入mapper.xml的全路径即可

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

Configuration:核心配置类:存放sqlMapConfig.xml解析出来的内容

MappedStatement:映射配置类:存放mapper.xml解析出来的内容

解析配置文件:使用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 2. 在resource中创建sqlMapConfig.xml 和 UserMapper.xml

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwjfwx.html