博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java web学习总结(二十三) -------------------编写自己的JDBC框架
阅读量:6224 次
发布时间:2019-06-21

本文共 11861 字,大约阅读时间需要 39 分钟。

一、元数据介绍

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

1.1、DataBaseMetaData元数据

  Connection.getDatabaseMetaData()获得代表DatabaseMetaData元数据的DatabaseMetaData对象。

  DataBaseMetaData对象的常用方法:

  • getURL():返回一个String类对象,代表数据库的URL。
  • getUserName():返回连接当前数据库管理系统的用户名。
  • getDatabaseProductName():返回数据库的产品名称。
  • getDatabaseProductVersion():返回数据库的版本号。
  • getDriverName():返回驱动驱动程序的名称。
  • getDriverVersion():返回驱动程序的版本号。
  • isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
复制代码
1     /** 2     * @Method: testDataBaseMetaData 3     * @Description: 获取数据库的元信息 4     * @Anthor:孤傲苍狼 5     * 6     * @throws SQLException 7     */  8     @Test 9     public void testDataBaseMetaData() throws SQLException {10         Connection conn = JdbcUtils.getConnection();11         DatabaseMetaData metadata = conn.getMetaData();12         //getURL():返回一个String类对象,代表数据库的URL13         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: testParameterMetaData 3     * @Description: 获取参数元信息 4     * @Anthor:孤傲苍狼 5     * 6     * @throws SQLException 7     */  8     @Test 9     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: testResultSetMetaData 3     * @Description: 结果集的元数据 4     * @Anthor:孤傲苍狼 5     * 6     * @throws Exception 7     */ 8     @Test 9     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: getConnection 45     * @Description: 获取数据库连接对象 46     * @Anthor:孤傲苍狼 47     * 48     * @return Connection数据库连接对象 49     * @throws SQLException 50     */  51     public static Connection getConnection() throws SQLException{ 52         return DriverManager.getConnection(url, username,password); 53     } 54      55     /** 56     * @Method: release 57     * @Description: 释放资源, 58     *     要释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象 59     * @Anthor:孤傲苍狼 60     * 61     * @param conn 62     * @param st 63     * @param rs 64     */  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: update 96     * @Description: 万能更新 97     * 所有实体的CUD操作代码基本相同,仅仅发送给数据库的SQL语句不同而已, 98     * 因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的SQL语句 99     * @Anthor:孤傲苍狼100     * @param sql 要执行的SQL101     * @param params 执行SQL时使用的参数102     * @throws SQLException103     */ 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
复制代码

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

复制代码
1 package me.gacl.util; 2  3 import java.sql.ResultSet; 4  5 /** 6 * @ClassName: ResultSetHandler 7 * @Description:结果集处理器接口 8 * @author: 孤傲苍狼 9 * @date: 2014-10-5 下午12:01:2710 *11 */ 12 public interface ResultSetHandler {13     14     /**15     * @Method: handler16     * @Description: 结果集处理方法17     * @Anthor:孤傲苍狼18     *19     * @param rs 查询结果集20     * @return21     */ 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: BeanHandler 9 * @Description: 将结果集转换成bean对象的处理器10 * @author: 孤傲苍狼11 * @date: 2014-10-5 下午12:00:3312 *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
复制代码

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: BeanListHandler11 * @Description: 将结果集转换成bean对象的list集合的处理器12 * @author: 孤傲苍狼13 * @date: 2014-10-5 下午12:00:0614 *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 list = new ArrayList();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
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
getAll() throws SQLException{40 String sql = "select * from account";41 Object params[] = {};42 return (List
) JdbcUtils.query(sql, params,new BeanListHandler(Account.class));43 }44 }
复制代码

转载于:https://www.cnblogs.com/zyl2016/p/6110621.html

你可能感兴趣的文章
MyEclipse启动失败现象以及解决办法
查看>>
Vmware vSphere常见问题汇总(四)
查看>>
反编译Silverlight项目
查看>>
Serving websites from svn checkout considered harmful
查看>>
迁移SVN注意事项及操作方法
查看>>
linux 的GPT分区
查看>>
getRealPath()和getContextPath()的区别
查看>>
浅析:AD组添加成员后为何客户端要注销?
查看>>
System Center Data Protection Manager 2007补助说明
查看>>
Fortune 500市场占有率分析:Compute、CDN、DNS
查看>>
RHCE 学习笔记(33) - Postfix
查看>>
Windows Server群集感知更新(CAU)-上
查看>>
LVM磁盘管理技术案例讲解
查看>>
SCCM 2012系列13 操作系统播发②
查看>>
Memcached 分布式缓存系统部署与调试
查看>>
开源网络备份软件bacula(功能特点与原理)
查看>>
《Essential Linux Device Drivers》第2章(下)
查看>>
Puppet扩展篇8-Puppet dashboard的部署及测试
查看>>
LCS2005客户端配置详解:LCS2005系列之二
查看>>
Linux网络管理员不得不了解的系统目录/proc/sys/net/
查看>>