javaweb基础(40)_jdbc框架

一、元数据介绍

  元数据指的是"数据库"、"表"、"列"的定义信息。

1.1、DataBaseMetaData元数据

  Connection.getDatabaseMetaData()获得代表DatabaseMetaData元数据的DatabaseMetaData对象。
  DataBaseMetaData对象的常用方法:

  • getURL():返回一个String类对象,代表数据库的URL。
  • getUserName():返回连接当前数据库管理系统的用户名。
  • getDatabaseProductName():返回数据库的产品名称。
  • getDatabaseProductVersion():返回数据库的版本号。
  • getDriverName():返回驱动驱动程序的名称。
  • getDriverVersion():返回驱动程序的版本号。
  • isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
复制代码
 1     /**2     * @Method: testDataBaseMetaData3     * @Description: 获取数据库的元信息4     * @Anthor:孤傲苍狼5     *6     * @throws SQLException7     */ 8     @Test9     public void testDataBaseMetaData() throws SQLException {
10         Connection conn = JdbcUtils.getConnection();
11         DatabaseMetaData metadata = conn.getMetaData();
12         //getURL():返回一个String类对象,代表数据库的URL
13         System.out.println(metadata.getURL());
14         //getUserName():返回连接当前数据库管理系统的用户名
15         System.out.println(metadata.getUserName());
16         //getDatabaseProductName():返回数据库的产品名称
17         System.out.println(metadata.getDatabaseProductName());
18         //getDatabaseProductVersion():返回数据库的版本号
19         System.out.println(metadata.getDatabaseProductVersion());
20         //getDriverName():返回驱动驱动程序的名称
21         System.out.println(metadata.getDriverName());
22         //getDriverVersion():返回驱动程序的版本号
23         System.out.println(metadata.getDriverVersion());
24         //isReadOnly():返回一个boolean值,指示数据库是否只允许读操作
25         System.out.println(metadata.isReadOnly());
26         JdbcUtils.release(conn, null, null);
27     }
复制代码

  运行结果如下:

  

1.2、ParameterMetaData元数据

  PreparedStatement.getParameterMetaData() 获得代表PreparedStatement元数据的ParameterMetaData对象。 
  Select * from user where name=? And password=?
  ParameterMetaData对象的常用方法:

  • getParameterCount(): 获得指定参数的个数
  • getParameterType(int param):获得指定参数的sql类型,MySQL数据库驱动不支持
复制代码
 1     /**2     * @Method: testParameterMetaData3     * @Description: 获取参数元信息4     * @Anthor:孤傲苍狼5     *6     * @throws SQLException7     */ 8     @Test9     public void testParameterMetaData() throws SQLException {
10         Connection conn = JdbcUtils.getConnection();
11         String sql = "select * from user wherer name=? and password=?";
12         //将SQL预编译一下
13         PreparedStatement st = conn.prepareStatement(sql);
14         ParameterMetaData pm = st.getParameterMetaData();
15         //getParameterCount() 获得指定参数的个数
16         System.out.println(pm.getParameterCount());
17         //getParameterType(int param):获得指定参数的sql类型,MySQL数据库驱动不支持
18         System.out.println(pm.getParameterType(1));
19         JdbcUtils.release(conn, null, null);
20     }
复制代码

1.3、ResultSetMetaData元数据

  ResultSet. getMetaData() 获得代表ResultSet对象元数据的ResultSetMetaData对象。 
  ResultSetMetaData对象的常用方法:

  • getColumnCount() 返回resultset对象的列数
  • getColumnName(int column) 获得指定列的名称
  • getColumnTypeName(int column)获得指定列的类型
复制代码
 1     /**2     * @Method: testResultSetMetaData3     * @Description: 结果集的元数据4     * @Anthor:孤傲苍狼5     *6     * @throws Exception7     */8     @Test9     public void testResultSetMetaData() throws Exception {
10         Connection conn = JdbcUtils.getConnection();
11         String sql = "select * from account";
12         PreparedStatement st  = conn.prepareStatement(sql);
13         ResultSet rs = st.executeQuery();
14         //ResultSet.getMetaData()获得代表ResultSet对象元数据的ResultSetMetaData对象
15         ResultSetMetaData metadata = rs.getMetaData();
16         //getColumnCount() 返回resultset对象的列数
17         System.out.println(metadata.getColumnCount());
18         //getColumnName(int column) 获得指定列的名称
19         System.out.println(metadata.getColumnName(1));
20         //getColumnTypeName(int column)获得指定列的类型
21         System.out.println(metadata.getColumnTypeName(1));
22         JdbcUtils.release(conn, st, rs);
23     }
复制代码

二、使用元数据封装简单的JDBC框架

  系统中所有实体对象都涉及到基本的CRUD操作
  所有实体的CUD操作代码基本相同,仅仅发送给数据库的SQL语句不同而已,因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的SQL语句。
  实体的R操作,除SQL语句不同之外,根据操作的实体不同,对ResultSet的映射也各不相同,因此可义一个query方法,除以参数形式接收变化的SQL语句外,可以使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中。

2.1、封装通用的update方法和qurey方法

  定义一个JdbcUtils工具类,工具类负责获取数据库连接,释放资源,执行SQL的update和query操作,代码如下:

复制代码
  1 package me.gacl.util;2 3 import java.io.InputStream;4 import java.sql.Connection;5 import java.sql.DriverManager;6 import java.sql.PreparedStatement;7 import java.sql.ResultSet;8 import java.sql.SQLException;9 import java.sql.Statement;10 import java.util.Properties;11 12 public class JdbcUtils {13 14     private static String driver = null;15     private static String url = null;16     private static String username = null;17     private static String password = null;18     19     static{20         try{21             //读取db.properties文件中的数据库连接信息22             InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");23             Properties prop = new Properties();24             prop.load(in);25             26             //获取数据库连接驱动27             driver = prop.getProperty("driver");28             //获取数据库连接URL地址29             url = prop.getProperty("url");30             //获取数据库连接用户名31             username = prop.getProperty("username");32             //获取数据库连接密码33             password = prop.getProperty("password");34             35             //加载数据库驱动36             Class.forName(driver);37             38         }catch (Exception e) {39             throw new ExceptionInInitializerError(e);40         }41     }42     43     /**44     * @Method: getConnection45     * @Description: 获取数据库连接对象46     * @Anthor:孤傲苍狼47     *48     * @return Connection数据库连接对象49     * @throws SQLException50     */ 51     public static Connection getConnection() throws SQLException{52         return DriverManager.getConnection(url, username,password);53     }54     55     /**56     * @Method: release57     * @Description: 释放资源,58     *     要释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象59     * @Anthor:孤傲苍狼60     *61     * @param conn62     * @param st63     * @param rs64     */ 65     public static void release(Connection conn,Statement st,ResultSet rs){66         if(rs!=null){67             try{68                 //关闭存储查询结果的ResultSet对象69                 rs.close();70             }catch (Exception e) {71                 e.printStackTrace();72             }73             rs = null;74         }75         if(st!=null){76             try{77                 //关闭负责执行SQL命令的Statement对象78                 st.close();79             }catch (Exception e) {80                 e.printStackTrace();81             }82         }83         84         if(conn!=null){85             try{86                 //关闭Connection数据库连接对象87                 conn.close();88             }catch (Exception e) {89                 e.printStackTrace();90             }91         }92     }93     94     /**95     * @Method: update96     * @Description: 万能更新97     * 所有实体的CUD操作代码基本相同,仅仅发送给数据库的SQL语句不同而已,98     * 因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的SQL语句99     * @Anthor:孤傲苍狼
100     * @param sql 要执行的SQL
101     * @param params 执行SQL时使用的参数
102     * @throws SQLException
103     */ 
104     public static void update(String sql,Object params[]) throws SQLException{
105         Connection conn = null;
106         PreparedStatement st = null;
107         ResultSet rs = null;
108         try{
109             conn = getConnection();
110             st = conn.prepareStatement(sql);
111             for(int i=0;i<params.length;i++){
112                 st.setObject(i+1, params[i]);
113             }
114             st.executeUpdate();
115             
116         }finally{
117             release(conn, st, rs);
118         }
119     }
120     
121     /**
122     * @Method: query
123     * @Description:万能查询
124     * 实体的R操作,除SQL语句不同之外,根据操作的实体不同,对ResultSet的映射也各不相同,
125     * 因此可义一个query方法,除以参数形式接收变化的SQL语句外,可以使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中。
126     * @Anthor:孤傲苍狼
127     *
128     * @param sql 要执行的SQL
129     * @param params 执行SQL时使用的参数
130     * @param rsh 查询返回的结果集处理器
131     * @return
132     * @throws SQLException
133     */ 
134     public static Object query(String sql,Object params[],ResultSetHandler rsh) throws SQLException{
135         
136         Connection conn = null;
137         PreparedStatement st = null;
138         ResultSet rs = null;
139         
140         try{
141             conn = getConnection();
142             st = conn.prepareStatement(sql);
143             for(int i=0;i<params.length;i++){
144                 st.setObject(i+1, params[i]);
145             }
146             rs = st.executeQuery();
147             /**
148              * 对于查询返回的结果集处理使用到了策略模式,
149              * 在设计query方法时,query方法事先是无法知道用户对返回的查询结果集如何进行处理的,即不知道结果集的处理策略,
150              * 那么这个结果集的处理策略就让用户自己提供,query方法内部就调用用户提交的结果集处理策略进行处理
151              * 为了能够让用户提供结果集的处理策略,需要对用户暴露出一个结果集处理接口ResultSetHandler
152              * 用户只要实现了ResultSetHandler接口,那么query方法内部就知道用户要如何处理结果集了
153              */
154             return rsh.handler(rs);
155             
156         }finally{
157             release(conn, st, rs);
158         }
159     }
160 }
复制代码

  在设计query方法时,对于查询返回的结果集处理使用到了策略模式,query方法事先是无法知道用户对返回的查询结果集如何进行处理的,即不知道结果集的处理策略, 那么这个结果集的处理策略就让用户自己提供,query方法内部就调用用户提交的结果集处理策略进行处理, 为了能够让用户提供结果集的处理策略,需要对用户暴露出一个结果集处理接口ResultSetHandler, 结果集处理器接口ResultSetHandler的定义如下:

复制代码
 1 package me.gacl.util;2 3 import java.sql.ResultSet;4 5 /**6 * @ClassName: ResultSetHandler7 * @Description:结果集处理器接口8 * @author: 孤傲苍狼9 * @date: 2014-10-5 下午12:01:27
10 *
11 */ 
12 public interface ResultSetHandler {
13     
14     /**
15     * @Method: handler
16     * @Description: 结果集处理方法
17     * @Anthor:孤傲苍狼
18     *
19     * @param rs 查询结果集
20     * @return
21     */ 
22     public Object handler(ResultSet rs);
23 }
复制代码

  用户只要实现了ResultSetHandler接口,那么就是针对查询结果集写了一个处理器,在query方法内部就调用用户自己写的处理器处理结果集。

2.2、编写常用的结果集处理器

  为了提高框架的易用性,我们可以事先就针对结果集写好一些常用的处理器,比如将结果集转换成bean对象的处理器,将结果集转换成bean对象的list集合的处理器。

2.2.1、BeanHandler——将结果集转换成bean对象的处理器

复制代码
 1 package me.gacl.util;2 3 import java.lang.reflect.Field;4 import java.sql.ResultSet;5 import java.sql.ResultSetMetaData;6 7 /**8 * @ClassName: BeanHandler9 * @Description: 将结果集转换成bean对象的处理器
10 * @author: 孤傲苍狼
11 * @date: 2014-10-5 下午12:00:33
12 *
13 */ 
14 public class BeanHandler implements ResultSetHandler {
15     private Class<?> clazz;
16     public BeanHandler(Class<?> clazz){
17         this.clazz = clazz;
18     }
19     public Object handler(ResultSet rs) {
20         try{
21             if(!rs.next()){
22                 return null;
23             }
24             Object bean = clazz.newInstance();
25             //得到结果集元数据
26             ResultSetMetaData metadata = rs.getMetaData();
27             int columnCount = metadata.getColumnCount();//得到结果集中有几列数据
28             for(int i=0;i<columnCount;i++){
29                 String coulmnName = metadata.getColumnName(i+1);//得到每列的列名
30                 Object coulmnData = rs.getObject(i+1);
31                 Field f = clazz.getDeclaredField(coulmnName);//反射出类上列名对应的属性
32                 f.setAccessible(true);
33                 f.set(bean, coulmnData);
34             }
35             return bean;
36         }catch (Exception e) {
37             throw new RuntimeException(e);
38         }
39     }
40 }
复制代码

2.2.2、BeanListHandler——将结果集转换成bean对象的list集合的处理器

复制代码
 1 package me.gacl.util;2 3 import java.lang.reflect.Field;4 import java.sql.ResultSet;5 import java.sql.ResultSetMetaData;6 import java.util.ArrayList;7 import java.util.List;8 9 /**
10 * @ClassName: BeanListHandler
11 * @Description: 将结果集转换成bean对象的list集合的处理器
12 * @author: 孤傲苍狼
13 * @date: 2014-10-5 下午12:00:06
14 *
15 */ 
16 public class BeanListHandler implements ResultSetHandler {
17     private Class<?> clazz;
18     public BeanListHandler(Class<?> clazz){
19         this.clazz = clazz;
20     }
21     
22     public Object handler(ResultSet rs) {
23         try{
24             List<Object> list = new ArrayList<Object>();
25             while(rs.next()){
26                 Object bean = clazz.newInstance();
27                 
28                 ResultSetMetaData  metadata = rs.getMetaData();
29                 int count = metadata.getColumnCount();
30                 for(int i=0;i<count;i++){
31                     String name = metadata.getColumnName(i+1);
32                     Object value = rs.getObject(name);
33                     
34                     Field f = bean.getClass().getDeclaredField(name);
35                     f.setAccessible(true);
36                     f.set(bean, value);
37                 }
38                 list.add(bean);
39             }
40             return list.size()>0?list:null;
41         
42         }catch (Exception e) {
43             throw new RuntimeException(e);
44         }
45     }
46 }
复制代码

  当框架自身提供的结果集处理器不满足用户的要求时,那么用户就可以自己去实现ResultSetHandler接口,编写满足自己业务要求的结果集处理器。

  有了上述的JdbcUtils框架之后,针对单个实体对象CRUD操作就非常方便了,如下所示:

复制代码
 1 package me.gacl.dao;2 3 import java.sql.SQLException;4 import java.util.List;5 import me.gacl.domain.Account;6 import me.gacl.util.BeanHandler;7 import me.gacl.util.BeanListHandler;8 import me.gacl.util.JdbcUtils;9 
10 public class AccountDao {
11 
12     public void add(Account account) throws SQLException{
13         String sql = "insert into account(name,money) values(?,?)";
14         Object params[] = {account.getName(),account.getMoney()};
15         JdbcUtils.update(sql, params);
16     }
17     
18     
19     public void delete(int id) throws SQLException{
20         String sql = "delete from account where id=?";
21         Object params[] = {id};
22         JdbcUtils.update(sql, params);
23     }
24     
25     public void update(Account account) throws SQLException{
26         
27         String sql = "update account set name=?,money=? where id=?";
28         Object params[] = {account.getName(),account.getMoney(),account.getId()};
29         JdbcUtils.update(sql, params);
30         
31     }
32     
33     public Account find(int id) throws SQLException{
34         String sql = "select * from account where id=?";
35         Object params[] = {id};
36         return (Account) JdbcUtils.query(sql, params, new BeanHandler(Account.class));
37     }
38     
39     public List<Account> getAll() throws SQLException{
40         String sql = "select * from account";
41         Object params[] = {};
42         return (List<Account>) JdbcUtils.query(sql, params,new BeanListHandler(Account.class));
43     }
44 }
复制代码

   编写的这个JDBC框架就是模拟Apache的DBUtils框架的实现,下一篇将具体介绍Apache的DBUtils框架。

转载于:https://www.cnblogs.com/estellez/p/5680584.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/430380.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab运动目标检测

matlab运动目标检测最近做了运动目标检测的程序和GUI实现&#xff0c;参考了挺多博客&#xff0c;很多都是对数据格式要求比较高或者存在一定的bug&#xff08;有些是因为版本不同&#xff09;&#xff0c;进行了一些修改。&#xff08;2014以后的matlab都能运行&#xff09;&a…

st-link v2怎么连接_三相交流电源的三角形和星形连接

相交流电是电能的一种输送形式&#xff0c;简称为三相电。三相交流电源&#xff0c;是由三个频率相同、振幅相等、相位依次互差120的交流电势组成的电源。我国发电厂和电力网生产、输送和分配的交流电都是三相交流电。1、三角形连接将三相电源的三个线圈&#xff0c;以一个线圈…

matlab程序聚类预测机器学习

matlabmatlab程序代做&#xff0c;数据挖掘&#xff0c;聚类&#xff0c;预测&#xff0c;分类&#xff0c;优化&#xff0c;建模。降重&#xff0c;降低重复率&#xff0c;24h出结果&#xff0c;最低1%重复。 机器学习&#xff0c;深度学习&#xff0c;神经网络代写&#xff0…

友益文书类似软件_团队成员分享 | 港中文翻译学姐:硬件不够,软件来凑;心之所愿,无所不能...

B学姐硬件不行的同学一定要努力提高自己对申请专业上的实习经验。饱腹诗书不够&#xff0c;也要有亲身实践后的体悟&#xff0c;这很加分。多对该行业背景现状进行思考&#xff0c;老师都喜欢有思想的学生&#xff0c;在后期面试也会给你带来惊喜。在读专业&#xff1a;港中文M…

iOS开发技巧,细节(二)

1.常量名称最好用static标识&#xff0c;例如下面的代码&#xff0c;包括其他一些只需要定义一次&#xff0c;之后不需要变化的变量也最好使用static static NSString *CellIdentifier "Cell"; 2.当设置视图控制器需要接受通知时&#xff0c;需要在dealloc取消监听 …

matlab支持向量机程序代做

matlab&#xff0c;支持向量机 回归&#xff0c;分类&#xff0c;都可以。另外决策树&#xff0c;神经网络都可以私人订制 **线性svm&#xff0c;二次svm&#xff0c;cubic svm

c++ qt5范例开发大全_使用yocto工具编译qt5.9.6总结

运行平台&#xff1a;OKMX6DL-C编译平台&#xff1a;Ubuntu 14.04.6 LTS编译工具&#xff1a;arm-poky-linux-gnueabi-gcc&#xff08;gcc version 5.3.0 (GCC) &#xff09;qt源码&#xff1a;qt-everywhere-opensource-src-5.9.6.tar.xz参考&#xff1a;嵌入式开发之Qt-5.9.6…

Android堆栈分析

在开发中&#xff0c;与界面跳转联系比较紧密的概念是Task&#xff08;任务&#xff09;和Back Stack&#xff08;回退栈&#xff09;。activity的启动模式会影响Task和Back Stack的状态&#xff0c; 进而影响用户体验。除了启动模式之外&#xff0c;Intent类中定义的一些标志&…

如何写一篇MBA论文-涉及matlab建模

如何写一篇MBA论文&#xff1f; 知乎 19 个回答方向&#xff0c;具体一点&#xff0c;不要太大。战略管理、薪酬管理、绩效考核、营销管理&#xff0c;客户关系管理、供应链管理、供应商选择与评价&#xff0c;库存问题。。论文模式第1章&#xff1a;绪论第2章&#xff1a;现状…

什么电脑的牌子好用_扬州诚招电动牙刷代理有什么牌子比较好用

扬州诚招电动牙刷代理有什么牌子比较好用&#xff0c;珈蓝电器实惠物美&#xff0c;为人类口腔事业的发展再创新贡献。扬州诚招电动牙刷代理有什么牌子比较好用&#xff0c; 很多人说电动牙刷是懒人神器&#xff0c; 但偷懒可以&#xff0c;口腔清洁效果可不能因此打折。电动牙…

360浏览器打不开网页_苹果移动端、PC端safari浏览器打不开网页的解决方案!

你还在为苹果自带的safari浏览器打不开网页而苦恼吗&#xff0c;接下来的答案会帮助你解决苦恼。苹果自带safari浏览器的设备分为两种&#xff1a;移动端、PC端。因此不同设备出现safari浏览器打不开网页的情况需要具体问题具体分析。最简单的问题往往最容易被我们忽视&#xf…

台式电脑如何截屏_买台式电脑如何避免成为被宰羔羊(一)

台式电脑的优点是很多的&#xff0c;比如价格便宜(和游戏本比起来)&#xff0c;比如性能发挥稳定(因为不受限于散热)&#xff0c;比如屏幕大看起来更舒服。但是和笔记本比起来&#xff0c;台式的水就非常深了&#xff0c;无论是线下实体店&#xff0c;还是线上网店&#xff0c;…

n型半导体和p型半导体的区别_VNX系列大流量工业型膜堆, 为半导体等行业提供超纯水!...

自20世纪80年代以来&#xff0c;IONPURE始终以为广泛的应用提供最优质的电化学解决方案延续着它的领导地位。IONPURE持续创新&#xff0c;于2004年推出了VNX 系列大流量CEDI膜堆&#xff0c;单个膜堆的名义产水流量最大可达12.5m3/h。IONPURE于2018年推出了单个膜堆的名义产水流…

属于db模式缺点的是什么_详解 Seata Golang 客户端 AT 模式及其使用

源码:point_down: seata-golang概述我们知道 Seata Java Client 的 AT 模式&#xff0c;通过代理数据源&#xff0c;实现了对业务代码无侵入的分布式事务协调机制&#xff0c;将与 Transaction Coordinator (TC) 交互的逻辑、Commit 的逻辑、Rollback 的逻辑&#xff0c;隐藏在…

如何在mfc主对话框中再显示子对话框_win10扩展显示器设置方法

使用win10系统的过程中&#xff0c;常常需要对win10系统扩展显示器进行设置。良多对电脑不太认识的用户不知道win10系统扩展显示器到底该如何设置?实在win10系统扩展显示器的设置方法非常简朴&#xff0c;下面小编教你win10扩展显示器设置方法。一些用户使用电脑时需要运行多个…

蓝牙驱动卸载后自动安装_Intel 蓝牙驱动安装教程

前言可能有些人之前没有搞定Intel蓝牙的驱动&#xff0c;今天就把蓝牙的驱动也发一下&#xff0c;实现Intel全家桶的驱动&#xff0c;到处倒腾换网卡也是挺折腾的。所支持的蓝牙IDIntelBluetoothFirmware 是一个用于在 macOS 中启用原生蓝牙的固件上传驱动&#xff0c;固件的二…

cad在线转低版本_为什么别人制图那么快?41个CAD实用技巧,3天轻松玩转CAD

获取更多业界资讯和深度好文● 点击蓝字关注我们 ●点击上方蓝色字体 关注我们我们在使用CAD制图时&#xff0c;总感觉自己的速度非常慢&#xff0c;为什么别人可以那么快的制图呢&#xff1f;今天就给大家分享一些CAD实用技巧&#xff0c;让你3天轻松玩转CAD。一、提高绘图效率…

不同协议的数据包如何处理_【项目申报专员】如何处理各种不同的项目申报工作呢...

前文我们说到了在企业做项目申报专员需要掌握的政策查询&#xff0c;以及申报流程解读工作&#xff0c;今天我给大家来分享在企业如何做好对不同项目的申报工作。说这个问题之前&#xff0c;我们先得了解一些背景知识。在企业做项目申报专员工作意味着什么&#xff1f;意味着事…

jsoup简单的爬取网页数据

/*** Project Name:JavaTest* File Name:BankOfChinaExchangeRate.java* Package Name:com.lee.javatest* Date:2016年7月22日下午1:34:09* Copyright (c) 2016年7月22日, Pwenlee All Rights Reserved.* */package com.lee.javatest;import java.io.Serializable; import java…