编辑自己的JDBC框架
元数据
- 在jdbc中获取数据库的定义,例如:数据库、表、列的定义信息。就用到元数据。
- 在jdbc中可以使用: 数据库元数据、参数元数据、结果集元数据
- (元数据定义相关api, ..MetaData)
public class App {
//1. 数据库元数据
@Test
public void testDB() throws Exception {
// 获取连接
Connection conn = JdbcUtil.getConnection();
// 获取数据库元数据
DatabaseMetaData metaData = conn.getMetaData();// alt + shift + L 快速获取方法返回值
System.out.println(metaData.getUserName());
System.out.println(metaData.getURL());
System.out.println(metaData.getDatabaseProductName());
}
//2. 参数元数据
@Test
public void testParams() throws Exception {
// 获取连接
Connection conn = JdbcUtil.getConnection();
// SQL
String sql = "select * from dept where deptid=? and deptName=?";
// Object[] values = {"tom","888"};
PreparedStatement pstmt = conn.prepareStatement(sql);
// 参数元数据
ParameterMetaData p_metaDate = pstmt.getParameterMetaData();
// 获取参数的个数
int count = p_metaDate.getParameterCount();
// 测试
System.out.println(count);
}
// 3. 结果集元数据
@Test
public void testRs() throws Exception {
String sql = "select * from dept ";
// 获取连接
Connection conn = JdbcUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
// 得到结果集元数据(目标:通过结果集元数据,得到列的名称)
ResultSetMetaData rs_metaData = rs.getMetaData();
// 迭代每一行结果
while (rs.next()) {
// 1. 获取列的个数
int count = rs_metaData.getColumnCount();
// 2. 遍历,获取每一列的列的名称
for (int i=0; i<count; i++) {
// 得到列的名称
String columnName = rs_metaData.getColumnName(i + 1);
// 获取每一行的每一列的值
Object columnValue = rs.getObject(columnName);
// 测试
System.out.print(columnName + "=" + columnValue + ",");
}
System.out.println();
}
}
}
使用元数据封装简单的JDBC框架
封装通用的update方法和qurey方法
public class JdbcUtils {
private static DataSource ds = null;
static {
try {
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties prop = new Properties();
prop.load(in);
BasicDataSourceFactory factory = new BasicDataSourceFactory();
ds = factory.createDataSource(prop);
System.out.println(ds);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
public static void release(Connection conn, Statement st, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if (st != null) {
try {
st.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//替换dao中的增删改方法
public static void update(String sql, Object params[]) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = getConnection();
st = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
st.setObject(i + 1, params[i]);
}
st.executeUpdate();
} finally {
release(conn, st, rs);
}
}
//替换所有dao中的查询 策略模式
public static Object query(String sql, Object params[], ResultSetHandler rsh) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = getConnection();
st = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
st.setObject(i + 1, params[i]);
}
rs = st.executeQuery();
return rsh.handler(rs);
} finally {
release(conn, st, rs);
}
}
}
集处理器接口ResultSetHandler
在设计query方法时,对于查询返回的结果集处理使用到了策略模式,query方法事先是无法知道用户对返回的查询结果集如何进行处理的,即不知道结果集的处理策略, 那么这个结果集的处理策略就让用户自己提供,query方法内部就调用用户提交的结果集处理策略进行处理, 为了能够让用户提供结果集的处理策略,需要对用户暴露出一个结果集处理接口ResultSetHandler, 结果集处理器接口ResultSetHandler的定义如下:
public interface ResultSetHandler {
public Object handler(ResultSet rs);
}
编写常用的结果集处理器
为了提高框架的易用性,我们可以事先就针对结果集写好一些常用的处理器,比如将结果集转换成bean对象的处理器,将结果集转换成bean对象的list集合的处理器。
- BeanHandler——将结果集转换成bean对象的处理器
public class BeanHandler implements ResultSetHandler {
private Class clazz;
public BeanHandler(Class clazz){
this.clazz = clazz;
}
public Object handler(ResultSet rs) {
try{
if(!rs.next()){
return null;
}
Object bean = clazz.newInstance();
ResultSetMetaData metadata = rs.getMetaData();
int columnCount = metadata.getColumnCount(); //得到有几列数据
for(int i=0;i<columnCount;i++){
String coulmnName = metadata.getColumnName(i+1); //得到列名
Object coulmnData = rs.getObject(i+1);
}
}
}
}
- BeanListHandler——将结果集转换成bean对象的list集合的处理器
public class BeanListHandler implements ResultSetHandler {
private Class clazz;
public BeanListHandler(Class clazz){
this.clazz = clazz;
}
public Object handler(ResultSet rs) {
try{
List list = new ArrayList();
while(rs.next()){
Object bean = clazz.newInstance();
ResultSetMetaData metadata = rs.getMetaData();
int count = metadata.getColumnCount();
for(int i=0;i<count;i++){
String name = metadata.getColumnName(i+1);
Object value = rs.getObject(name);
Field f = bean.getClass().getDeclaredField(name);
f.setAccessible(true);
f.set(bean, value);
}
list.add(bean);
}
return list.size()>0?list:null;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}