把驱动注册和释放连接资源封装了一个工具类
package com.yidongxueyuan.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/*
* 对JDBC 进行封装:
*/
public class JdbcUtils2 {
//准备数据库的四大参数:
private static final String driver ="com.mysql.jdbc.Driver";
private static final String url ="jdbc:mysql://localhost:3306/jdbc01";
private static final String username ="root";
private static final String password ="root";
/*
* 驱动: 只需要注册一次就OK
*
*/
static{
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/*
* 1:创建工具类: 直接获得一个连接对象:
*/
public static Connection getConnection (){
try {
Connection connection = DriverManager.getConnection(url, username, password);
return connection;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/*
* 定义一个方法: 释放资源: 直接将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;
}
}
}
/结果集的封装: 将rs 封装到javaBean 当中:
package com.yidongxueyuan.dbassist;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
//提供一种结果处理器: 将rs 封装到javaBean 当中:
class BeanHandler implements ResultSetHandler {
//准备一个目的:
private Class clazz; //目标对象:
public BeanHandler(Class clazz){
this.clazz = clazz;
}
@Override
public Object handler(ResultSet rs) {
/*
* rs 封装了结果集:
* rs当中的结果集设定到javaBean当中
*
* rs ----> 元数据对象: 列的名称: 列的个数:
* id name money ---->属性名称: ---->反射:Field
* Field.set();
*/
try {
while(rs.next()){
//目标对象:
Object bean = clazz.newInstance();//无参数构造器:
//获得是: 结果集的元数据:
ResultSetMetaData rsmd = rs.getMetaData();
//列的个数:
int count = rsmd.getColumnCount();
for(int i = 0 ; i< count ; i++){
//字段的名称: 字段的名称和列的名称对应:
String fieldname = rsmd.getColumnName(i+1);
//设置值:
Object fieldValue = rs.getObject(fieldname);
//反射:
Field field = clazz.getDeclaredField(fieldname);
//私有的不能直接访问;
field.setAccessible(true);
field.set(bean, fieldValue);
}
return bean;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
}
读和写的封装:
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;
}
}
}