打卡:2019年3月17日22:21:03
编写自己的JDBC框架(为学习DBUtil框架、Spring JDBCTemplate做准备)
1、数据库元信息的获取(为写框架而准备)
元信息:
数据库的一些定义信息。比如用的是什么数据库等,表的定义信息等。
元信息:
数据库的元信息: DataBaseMetaData
参数的元信息: ParameterMetaData
和结果集相关:: ResultMetaData
案例:代码的演示,获得数据库,参数,结果集的参数信息。
package com.yidongxueyuan.meta;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import org.junit.Test;
import com.yidongxueyuan.utils.C3P0Util;
/*
* 元数据的获取:
*
*/
public class MetaDemo {
//获得数据库的一些元信息:
@Test
public void testname() throws Exception {
Connection conn = C3P0Util.getConnection();
//获得链接对象的元数据对象:
DatabaseMetaData dmd = conn.getMetaData();
//数据数据库的名称;
String dsname = dmd.getDatabaseProductName();
System.out.println(dsname);
int num = dmd.getDefaultTransactionIsolation();
System.out.println(num);// Connection 接口当中进行查询:
}
//获得参数的元信息:
@Test
public void test2() throws Exception {
Connection conn = C3P0Util.getConnection();
PreparedStatement stmt = conn.prepareStatement("??????");
//获得PreparedStatement 元数据对象:
ParameterMetaData pmd = stmt.getParameterMetaData();
// 获得占位符的个数:
int num = pmd.getParameterCount();
System.out.println(num);// 6
}
//结果集的元数据:
@Test
public void test3() throws Exception {
Connection conn = C3P0Util.getConnection();
PreparedStatement stmt = conn.prepareStatement("select * from account");
ResultSet rs = stmt.executeQuery();
//获得结果集的元数据:
ResultSetMetaData rsm = rs.getMetaData();
//
int count = rsm.getColumnCount();//总列数:
/*System.out.println(cols);*/
/*
int type = rsm.getColumnType(1);// 4 Type
System.out.println(type);*/
for(int i=0 ; i<count; i++){
String columnName = rsm.getColumnName(i+1);
System.out.println(columnName);
int type = rsm.getColumnType(i+1);
System.out.println(type);
}
}
}
2、编写JDBC框架:(策略设计模式)
编写数据库写的操作: 写的操作包括: 增删改:
读取数据的操作,查询操作。 查询操作,需要对结果集进项相关的处理。
作为一个框架的设计者不能满足所有用户的需求,在这儿采用策略的设计模式,对结果集进行处理。
策略的设计模式: 谁用谁知道,由具体的调用者对结果集进行处理
定义查询的方法:
结果处理器: 定义一个接口:对结果集进行处理。 具体的实现方式由处理者绝对,策略的设计模式。
提供一个结果集处理器的处理方式:
package com.yidongxueyuan.dbassist;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.yidongxueyuan.utils.C3P0Util;
import com.yidongxueyuan.utils.DBCPUtil;
/*
* 设定一个框架:
* 能够完成数据库的读和写的操作:
* select * from tableName where id=? and username=?
* 定义读的方法; query(String sql, Object[] params );
*
* 写操作:
* delete from tableName where id=?
* update tableName set name=? , password=? where id=?
* insert into tableName values(?,?,?);
* 定义写的方法: update(String sql , Object [] params );
*
* 总结: 删除, 修改, 插入, 都属于数据库的写操作: 只有sql 语句不同,
* 通过动态的传递sql 语句, sql 语句里面的占位符的个数不确定, 所以
* 可变参数的数据来传递。
*
*/
public class DBAssist {
//写的操作;
public void update(String sql, Object ... params) throws Exception{
//获得链接对象;
Connection connection = C3P0Util.getConnection();
//stmt容器:
PreparedStatement pstmt = connection.prepareStatement(sql);
//设置sql 语句当中的占位符号:
//参数的元数据对象:
ParameterMetaData pmd = pstmt.getParameterMetaData();
//获得?的个数:
int count = pmd.getParameterCount();
//循环遍历每一个?, 给每一个?赋值, 值来源于可变参数的数组:
if(count > 0){
// 增强健壮性;
if(params == null){
throw new RuntimeException("必须传递参数的值");
}
if(params.length != count){
throw new RuntimeException("传递的参数个数不正确");
}
for(int i =0 ;i<count; i++){
pstmt.setObject(i+1, params[i]);
}
}
int num = pstmt.executeUpdate();
System.out.println(num);
//释放资源 //
DBAssist.release(null, pstmt, connection);//还会池子当中
}
//查询; 使用策略的设计模式, 对结果集进行处理: Object
public Object query (String sql, ResultSetHandler h, Object ... params){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DBCPUtil.getConnection(); //使用dbcp 数据源;
pstmt = conn.prepareStatement(sql);
// 给占位符赋值:
ParameterMetaData pmd = pstmt.getParameterMetaData();
int count = pmd.getParameterCount();
if(count > 0){
// 增强健壮性;
if(params == null){
throw new RuntimeException("必须传递参数的值");
}
if(params.length != count){
throw new RuntimeException("传递的参数个数不正确");
}
for(int i =0 ;i<count; i++){
pstmt.setObject(i+1, params[i]);
}
}
//执行;
rs = pstmt.executeQuery();
// rs 查询到的结果集: 要想把结果集封装到哪里去? 作为一个框架的设计者, 不能确定用户要封装到哪里去?
// 用户可能封装javaBean , 封装到List 集合《 封装到数组当中。 还可能封装到map 集合当中:
// 作为一个优秀的框架的设计者, 应该提供常见的结果集处理器: 就是把查询的结果具体的封装到哪里? 常用的应该提供:
//采用策略的设计模式: 谁用谁决定:
return h.handler(rs);
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
DBAssist.release(rs, pstmt, conn);
}
}
//定义一个释放资源的方法;
/*
* 定义一个方法: 释放资源: 直接将rs stmt conn 全部释放:
*/
public static void release(ResultSet rs ,Statement stmt , Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs=null;
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt=null;
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn=null;
}
}
}