简易JDBC框架实现过程详解

网友投稿 530 2023-06-23

简易JDBC框架实现过程详解

简易JDBC框架实现过程详解

1 准备

JDBC 基本知识

JDBC元数据知识

反射基本知识

2: 两个问题

业务背景:系统中所有实体对象都涉及到基本的CRUD操作。所有实体的CUD操作代码基本相同,仅仅是发送给数据库的sql语句不同而已,因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的sql语句。

实体的R操作,除sql语句不同之外,根据操作的实体不同,对ResultSet的映射也各不相同,因此可定义一个query方法,除以参数形式接收变化的sql语句外,可以使用策略模式由query方法的调用者决定如何把ResultSet中的数据映射到实体对象中。

3: JDBC 封装 update query方法

public class JdbcNewUtils {

private JdbcNewUtils() {}

/**

* 这里可以使用properties进行替换

*/

private static final String USER = "root";

private static final String PWD = "root";

private static final String URL = "jdbc:mysql://127.0.0.1:3306/day?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&generateSimpleParameterMetadata=true";

private static final String DRIVER= "com.mysql.jdbc.Driver";

static {

try {

Class.forName(DRIVER);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

public static Connection getConnection() throws SQLException {

Connection connection = DriverManager.getConnection(URL, USER, PWD);

return connection;

}

/**

* CUD 返回影响数目

* @param sql

* @param args

* @return int

*/

public static int update(String sql,Object [] args) {

PreparedStatement ps = null;

Connection conn = null;

try {

conn=getConnection();

ps = conn.prepareStatement(sql);

for (int i = 1; i <= args.length; i++) {

ps.setObject(i, args[i-1]);

}

return ps.executeUpdate();

} catch (SQLException e) {

e.printStackTrace();

}finally {

close(conn, ps);

}

return 0;

}

/**

* 查询结果封装Bean

* @param sql

* @param args

* @param rsh

* @return Object

*/

public static Object query(String sql,Object [] args,ResultSetHandler rsh) {

PreparedStatement ps = null;

Connection conn = null;

try {

conn=getConnection();

ps = conn.prepareStatement(sql);

for (int i = 0; i < args.length; i++) {

ps.setObject(i+1, args[i]);

}

return rsh.handle(ps.executeQuery());

} catch (SQLException e) {

e.printStackTrace();

}finally {

close(conn, ps);

}

return null;

}

/**

* 关闭所有打开的资源

*/

public static void close(Connection conn, Statement stmt) {

if(stmt!=null) {

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if(conn!=null) {

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

/**

* 关闭所有打开的资源

*/

public static void close(Connection conn, Statement stmt, ResultSet rs) {

if(rs!=null) {

try {

rs.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

close(conn, stmt);

}

}

4: query

每次查询根据查询的参数不同, 返回的ResultSet 也不同, 这个规则我们需要单独编写规则解析器, 这里用到了策略设计模式,

将ResultSetHandler 定义解决问题的接口, handle为那些需要实现的具体解决的办法

public interface ResultSetHandler {

Object handle(ResultSet resultSet);

}

下面我实现了Beanhandler 和 BeanListHandler 分别是 单个的Bean 和一个列表的Bean

package jdbc.simpleframwork;

import java.lang.reflect.Field;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.SQLException;

public class BeanHandler implements ResultSetHandler {

private Class> obj;

public BeanHandler(Class> obj) {

this.obj = obj;

}

@Override

public Object handle(ResultSet resultSet){

try {

if(!resultSet.next()) {

return null;

}

Object instance = obj.newInstance();

ResultSetMetaData metaData = resultSet.getMetaData();

int count = metaData.getColumnCount();

for(int i=1;i<=count;i++) {

Field f = obj.getDeclaredField(metaData.getColumnName(i));

f.setAccessible(true);

f.set(instance, resultSet.getObject(i));

}

return instance;

} catch (InstantiationException | IllegalAccessException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

} catch (NoSuchFieldException e) {

e.printStackTrace();

} catch (SecurityException e) {

e.printStackTrace();

}

return null;

}

}

package jdbc.simpleframwork;

import java.lang.reflect.Field;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.util.ArrayList;

public class BeanListHandler implements ResultSetHandler {

private Class> clazz;

public BeanListHandler(Class> clazz) {

super();

this.clazz = clazz;

}

@Override

public Object handle(ResultSet resultSet) {

try {

ArrayList objlist = new ArrayList<>();

ResultSetMetaData metaData = resultSet.getMetaData();

int count = metaData.getColumnCount();

while (resultSet.next()) {

Object instace = clazz.newInstance();

for (int i = 0; i < count; i++) {

Field f = clazz.getDeclaredField(metaData.getColumnName(i + 1));

f.setAccessible(true);

f.set(instace, resultSet.getObject(i + 1));

f.setAccessible(false);

}

objlist.add(instace);

}

return objlist;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

}

5 测试

public class TestFramwork {

public static void main(String[] args) throws SQLException {

Connection conn = JdbcNewUtils.getConnection();

String sql = "select * from student where id=?";

PreparedStatement ps = conn.prepareStatement(sql);

Student stu = (Student) JdbcNewUtils.query(sql, new Object[] { 1 }, new BeanHandler(Student.class));

System.out.println(stu);

String sql2 = "select * from student";

ArrayList list = (ArrayList) JdbcNewUtils.query(sql2, new Object[] {},

new BeanListHandler(Student.class));

System.out.println(list);

}

}

6: 总结

Update系列操作:

对于CUD操作,SQL只有站位符号的多少发生了改变,对于传递参数才是我们需要关注的地方,但是JDBC提供了一系列传递参数解析的办法,通过set系列函数,将参数值传递进行,所以我们只需要封装一个通用的update即可

Query系列操作

对R操作,就复杂得多,SQL语句的不同,返回的ResultSet也不同,可以单个Bean 或者一个List,一个Map等,可以看出来,实际上很多框架提供的也就是这些方法的封装

对了 真正应用上 我们的DAO 一边是 下面的写法

public class AccountDao {

public void add(Account account) throws SQLException{

String sql = "insert into account(name , money) values(?, ?)";

Object[] params = {account.getName(), account.getMoney()};

JdbcUtils.update(sql, params);

}

public void delete(int id ) throws SQLException{

String sql = "delete from account where id = ?";

Object[] params = {id};

JdbcUtils.update(sql, params);

}

public void update(Account account) throws SQLException{

String sql = "update account set name = ?, money = ? where id = ?";

Object params[] = {account.getName(), account.getMoney(), account.getId()};

JdbcUtils.update(sql, params);

}

public Account find(int id ) throws SQhttp://LException{

String sql = "select * from account where id = ?";

Object params[] = {id};

return (Account) JdbcUtils.query(sql, params, new BeanHandler(Account.class));

}

public List getAll() throws SQLException{

String sql = "select * from account";

Object params[] = {};

return (List)JdbcUtils.query(sql, params, new BeanListHandler(Account.class));

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:在项目中集成jetty server步骤解析
下一篇:深入浅析springboot中static和templates区别
相关文章

 发表评论

暂时没有评论,来抢沙发吧~