手写简单JDBC
自定义一个简单的jdbc框架,包含增加,修改,删除,查询方法,增,删改,比较简单 传入要执行的sql 和(prepareStatement)预编译 是需要的参数,本例子中使用可变参数 传入,通过下面代码设置预编译时需要的参数。 查询方法,将查询的的结果封装成相应的一个个对象,再将对象放入list返回。
1 2 3 4 5 6 7 | // 设置参数 ParameterMetaData parameterMetaData = stmt.getParameterMetaData(); int count = parameterMetaData.getParameterCount(); for ( int i = 1 ; i <= count; i++) { stmt.setObject(i, obj[i - 1 ]); } stmt.execute(); |
查询方法主要是将结果集封装成一个个javaBean 具体操作如下:
1 用rs.getMetaData();方法获得结果集元数据 ResultSetMetaData 结果集元数据 ---- 获得结果集列名称、数量、类型*/
ResultSetMetaData resultSetMetaData=rs.getMetaData();
2 获得总列数
int count =resultSetMetaData.getColumnCount();
3 内省技术获得类 要求要传入相应的 类.class */
BeanInfo beanInfo = Introspector.getBeanInfo(domainClass);
4 利用内省技术获得类中所有属性
PropertyDescriptor[] propertyDescriptors=beanInfo.getPropertyDescriptors();
5 遍历结果集
《1》 遍历所有的列
《2》 将所有的属性和每一列的字段比较 ,如果属性名和列的字段名相同 利用反射技术将该列的的值赋给和该列名字相同的属性。
内省:
内省(Introspector)是Java语言对JavaBean类属性、事件的处理方法
例如类User中有属性name,那么必定有getName,setName方法,我们可以通过他们来获取或者设置值,这是常规操作。
Java提供了一套API来访问某个属性的getter/setter方法,这些API存放在java.beans中
反射:
Java反射机制是在运行中,对任意一个类,能够获取得到这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法;
这种动态获取类信息以及动态调用类对象方法的功能叫做Java语言的反射机制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | /*1 ResultSetMetaData 结果集元数据 ---- 获得结果集列名称、数量、类型*/ ResultSetMetaData resultSetMetaData=rs.getMetaData(); /*2 获得总列数*/ int count =resultSetMetaData.getColumnCount(); /*3 内省技术获得类 要求要传入相应的 类.class */ BeanInfo beanInfo = Introspector.getBeanInfo(domainClass); /*4 获得所有属性*/ PropertyDescriptor[] propertyDescriptors=beanInfo.getPropertyDescriptors(); /*5 遍历结果集*/ while (rs.next()){ /*<1> 获取泛型实例对象*/ T t=domainClass.newInstance(); /*<2>遍历每一个数据库中的字段 看是否与属性名字匹配 如果匹配就将 数据库中的取得的字段值放入属性中*/ for ( int i= 1 ;i<=count;i++){ //获得列名 String columnName=resultSetMetaData.getColumnName(i); for (PropertyDescriptor pd:propertyDescriptors){ /*属性名字和数据库中的名字匹配的时候为属性赋值*/ if (columnName.equals(pd.getName())){ /*username public void com.goke.User.setUsername(java.lang.String)pd.getWriteMethod() userpwd public void com.goke.User.setUserpwd(java.lang.String)pd.getWriteMethod() userdesc public void com.goke.User.setUserdesc(java.lang.String)pd.getWriteMethod() id 没有set 方法则显示 */ //获得对应的set 方法 Method setMethod=pd.getWriteMethod(); setMethod.invoke(t, new Object[]{rs.getObject(columnName)}); } } } list.add(t); } |
详细代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | package com.goke; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.ParameterMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.rl.JDBCUtil; public class JDBCIfram { public static void main(String[] args) { BeanHanderInterface<User> beanHander= new BeanHanderImpl<>(User. class ); /*String sqlInsert="insert into user (username,userpwd) values(?,?)"; Object [] obje={"liming","liming"}; insert(sqlInsert, obje); String sql="delete from user where username=? and userpwd=?"; //Object [] obj={"zhang","lei"}; delete(sql, new Object[]{"zhang","lei"}); */ String sql= "select * from user" ; System.out.println(query(sql, beanHander, null )); } /*查询*/ public static <T> List<T> query(String sql, BeanHanderInterface<T> beanHander,Object ...arg){ T obj = null ; List<T> list= new ArrayList<>(); Connection conn = null ; PreparedStatement stmt = null ; ResultSet rs = null ; try { conn = JDBCUtil.getConnection(); stmt = conn.prepareStatement(sql); // 设置参数 ParameterMetaData parameterMetaData = stmt.getParameterMetaData(); int count = parameterMetaData.getParameterCount(); for ( int i = 1 ; i <= count; i++) { stmt.setObject(i, arg[i - 1 ]); } rs = stmt.executeQuery(); list = beanHander.hander(rs); } catch (SQLException e) { e.printStackTrace(); } finally { //JDBCUtil.colseResource(conn, stmt, rs); } return list; } /*插入*/ public static void insert(String sql ,Object[] obj){ Connection conn = null ; PreparedStatement stmt = null ; ResultSet rs = null ; try { conn = JDBCUtil.getConnection(); stmt = conn.prepareStatement(sql); // 设置参数 ParameterMetaData parameterMetaData=stmt.getParameterMetaData(); int count =parameterMetaData.getParameterCount(); for ( int i = 1 ; i <= count; i++) { stmt.setObject(i, obj[i - 1 ]); } stmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtil.colseResource(conn, stmt, rs); } } /*修改*/ public static void update(String sql ,Object[] obj){ Connection conn = null ; PreparedStatement stmt = null ; ResultSet rs = null ; try { conn = JDBCUtil.getConnection(); stmt = conn.prepareStatement(sql); // 设置参数 ParameterMetaData parameterMetaData = stmt.getParameterMetaData(); int count = parameterMetaData.getParameterCount(); for ( int i = 1 ; i <= count; i++) { stmt.setObject(i, obj[i - 1 ]); } stmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtil.colseResource(conn, stmt, rs); } } /*删除*/ public static void delete(String sql ,Object[] obj){ Connection conn = null ; PreparedStatement stmt = null ; ResultSet rs = null ; try { conn = JDBCUtil.getConnection(); stmt = conn.prepareStatement(sql); // 设置参数 ParameterMetaData parameterMetaData = stmt.getParameterMetaData(); int count = parameterMetaData.getParameterCount(); for ( int i = 1 ; i <= count; i++) { stmt.setObject(i, obj[i - 1 ]); } stmt.execute(); } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtil.colseResource(conn, stmt, rs); } } } /*创建 封装查询结果为实体类的接口*/ interface BeanHanderInterface<T> { public List<T> hander(ResultSet rs); //将结果集传过来 封装成T实体类 } /*接口实现类*/ class BeanHanderImpl<T> implements BeanHanderInterface<T>{ private Class<T> domainClass; public BeanHanderImpl(Class<T> domainClass) { super (); this .domainClass = domainClass; } @Override public List<T> hander(ResultSet rs) { List<T> list= new ArrayList<>(); try { /*1 ResultSetMetaData 结果集元数据 ---- 获得结果集列名称、数量、类型*/ ResultSetMetaData resultSetMetaData=rs.getMetaData(); /*2 获得总列数*/ int count =resultSetMetaData.getColumnCount(); /*3 内省技术获得类 要求要传入相应的 类.class */ BeanInfo beanInfo = Introspector.getBeanInfo(domainClass); /*4 获得所有属性*/ PropertyDescriptor[] propertyDescriptors=beanInfo.getPropertyDescriptors(); /*5 遍历结果集*/ while (rs.next()){ /*<1> 获取泛型实例对象*/ T t=domainClass.newInstance(); /*<2>遍历每一个数据库中的字段 看是否与属性名字匹配 如果匹配就将 数据库中的取得的字段值放入属性中*/ for ( int i= 1 ;i<=count;i++){ //获得列名 String columnName=resultSetMetaData.getColumnName(i); for (PropertyDescriptor pd:propertyDescriptors){ /*属性名字和数据库中的名字匹配的时候为属性赋值*/ if (columnName.equals(pd.getName())){ /*username public void com.goke.User.setUsername(java.lang.String)pd.getWriteMethod() userpwd public void com.goke.User.setUserpwd(java.lang.String)pd.getWriteMethod() userdesc public void com.goke.User.setUserdesc(java.lang.String)pd.getWriteMethod() id 没有set 方法则显示 */ //获得对应的set 方法 Method setMethod=pd.getWriteMethod(); setMethod.invoke(t, new Object[]{rs.getObject(columnName)}); } } } list.add(t); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IntrospectionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; } } |
本列中简单实现了增加,删除,修改,和查询方法, 在查询中将结果封装成类时是考虑数据库字段和属性名相同的情况,没有对数据库字段和属性名不同的情况做处理, 如 数据库字段为user_name 属性字段为username
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景
· 从零实现富文本编辑器#3-基于Delta的线性数据结构模型
· 记一次 .NET某旅行社酒店管理系统 卡死分析
· 长文讲解 MCP 和案例实战
· Hangfire Redis 实现秒级定时任务,使用 CQRS 实现动态执行代码
· C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景
· 管理100个小程序-很难吗
· 在SqlSugar的开发框架中增加对低代码EAV模型(实体-属性-值)的WebAPI实现支持
· .NET Core中的配置Configuration实战
· 记一次 .NET某工控任务调度系统 卡死分析