企业如何通过vue小程序开发满足高效运营与合规性需求
530
2023-06-23
简易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
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
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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~