JDBC 框架

有两种方法可以实现对数据库统一的增删改查操作,一个是利用反射,一个是利用元数据。前者虽然实现简单,但是反射毕竟性能较低,不适合在移动设备上使用,下面我用两种方法实现 JDBC 的一个小框架。

 

一、利用反射技术

      思路分析:

                     我们对数据库的增删改查操作可以分为两类,一类是增删改即 update,一类是查询即 select。之所以这样分,是因为对数据库的增删改不需要涉及到 Bean 的操作,而查询就要分析我们要查询的对象。

                     首先我们考虑更新,我们需要用户将 sql 语句,参数传递给我们,然后我们可以利用 PreparedStatement 对象动态的将参数加入到预编译的 sql 中,这很简单,只需几行代码搞定,参数列表可以是数组,也可以是可变参。

                      查询操作我们除了需要知道上面的两个参数以外,还要知道我们操作的是什么 Bean,这也有两种方式,一种是让用户将 Bean 的 Class 字节码给我们,我们利用反射获取 Bean 里面的每一个字段,之后通过字段名内省出 Bean 的所有属性,从而达到将数据封装到 Bean 的效果。还有一种方式是用到策略模式,我们既然不知道要操作什么 Bean,那么我们就让用户来决定,我们只需要给用户暴露一个接口,将 ResultSet 传过去,用户就可以自己封装数据。为了简化用户操作,我们可以事先写好几个常用的实现类。下面我就演示如何用几行代码搞定增删改查操作:

	public static <T> T crud(Class<?> type, String sql, Object... param) {
		Connection con = getConnection();
		PreparedStatement ps = null;
		ResultSet rs = null;
		T t = null;
		try {
			ps = con.prepareStatement(sql);
			for (int i = 1; param != null && i <= param.length; i++) {
				ps.setObject(i, param[i - 1]);
			}
			boolean execute = ps.execute();
			if (execute) {
				t = (T) type.newInstance();
				rs = ps.getResultSet();
				rs.next();
				Field[] fields = t.getClass().getDeclaredFields();
				for (int i = 0; i < fields.length; i++) {
					String fieldName = fields[i].getName();
					Object data = rs.getObject(fieldName);
					PropertyDescriptor descriptor = new PropertyDescriptor(
							fieldName, t.getClass());
					Method method = descriptor.getWriteMethod();
					method.invoke(t, data);
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			release(con, ps, rs);
		}
		return t;
	}


 

 二、利用元数据

       思路分析:

                     上面的代码虽然简单,但是性能比较差,如果我们利用数据库元数据信息,就可以大大提升效率。至于数据库的元数据可以分为:DataBaseMetaData、ParameterMetaData、ResultSetMetaData。他们分别是数据库元数据,我们可以通过 DataBaseMetaData 获取与库相关的信息,比如 url、用户名、版本号、驱动名等等。ParameterMetaData 我们可以获取 sql 语句中的参数个数、参数类型。ResultSetMetaData 可以得到表的列数、指定列的名称、指定列的类型等。有了以上信息,我们为我们利用元数据实现 CRUD 很简单。这种方式我将利用策略模式实现。就是将封装数据的行为交给用户,当然,框架就是更方便的满足用户需求,我也将写两个实现类。

工具类:

package cn.dk.tools;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class CrudTool {

	private static ComboPooledDataSource source = new ComboPooledDataSource(
			"mysql");

	public static Connection getConnection() {
		try {
			return source.getConnection();
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}

	public static void release(Connection con, Statement st, ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
			} finally {
				try {
					st.close();
				} catch (SQLException e) {
				} finally {
					try {
						st.close();
					} catch (SQLException e) {

					} finally {
						try {
							con.close();
						} catch (SQLException e) {
						}
					}
				}
			}
		}
	}

	public static int update(String sql, Object[] param) {
		Connection con = getConnection();
		PreparedStatement ps = null;
		try {
			ps = con.prepareStatement(sql);
			for (int i = 0; param != null && i < param.length; i++) {
				ps.setObject(i + 1, param[i]);
			}
			return ps.executeUpdate();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public static Object select(String sql, Object[] param,
			IResultSetHandler handler) {
		Connection con = getConnection();
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			ps = con.prepareStatement(sql);
			for (int i = 0; param != null && i < param.length; i++) {
				ps.setObject(i + 1, param[i]);
			}
			rs = ps.executeQuery();
			return handler.fillObject(rs);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		} finally {
			release(con, ps, rs);
		}
	}

	public static Number selectNum(String sql, Object[] param) {
		Connection con = getConnection();
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			ps = con.prepareStatement(sql);
			for (int i = 0; param != null && i < param.length; i++) {
				ps.setObject(i + 1, param[i]);
			}
			rs = ps.executeQuery();
			if(rs.next())
				return (Number) rs.getObject(1);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		} finally {
			release(con, ps, rs);
		}
		return 0;
	}
}

 

实现类1:封装 Bean

package cn.dk.tools;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

@SuppressWarnings("unchecked")
public class BeanHandler implements IResultSetHandler {

	public BeanHandler(Class clazz) {
		this.clazz = clazz;
	}

	private Class clazz;

	public Object fillObject(ResultSet rs) {
		ResultSetMetaData metaData;
		try {
			Object instance = clazz.newInstance();
			if (rs != null && rs.next()) {
				
				metaData = rs.getMetaData();
				int columnCount = metaData.getColumnCount();
				for (int i = 0; i < columnCount; i++) {
					String propertyName = metaData.getColumnName(i + 1);
					Object object = rs.getObject(propertyName);
					PropertyDescriptor descriptor = new PropertyDescriptor(
							propertyName, clazz);
					Method writeMethod = descriptor.getWriteMethod();
					writeMethod.invoke(instance, object);
				}
			}
			return instance;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}


实现类2:返回集合

package cn.dk.tools;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("unchecked")
public class BeanListHandler implements IResultSetHandler {

	public BeanListHandler(Class clazz) {
		this.clazz = clazz;
	}

	private Class clazz;

	public Object fillObject(ResultSet rs) {
		ResultSetMetaData metaData;
		try {
			List list = null;
			if (rs != null) {
				list = new ArrayList();
				while (rs.next()) {
					Object instance = clazz.newInstance();
					metaData = rs.getMetaData();
					int columnCount = metaData.getColumnCount();
					for (int i = 0; i < columnCount; i++) {
						String propertyName = metaData.getColumnName(i + 1);
						Object object = rs.getObject(propertyName);
						PropertyDescriptor descriptor = new PropertyDescriptor(
								propertyName, clazz);
						Method writeMethod = descriptor.getWriteMethod();
						writeMethod.invoke(instance, object);
					}
					list.add(instance);
				}
			}
			return list;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}


      这种方法就给了我们一种思想,一种解决问题的思路。

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值