编写JDBC框架:(策略设计模式)

Posted 学海无涯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编写JDBC框架:(策略设计模式)相关的知识,希望对你有一定的参考价值。

package com.itheima.domain;
//一般:实体类的字段名和数据库表的字段名保持一致
//约定优于编码
public class Account {
    private int id;
    private String name;
    private float money;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public float getMoney() {
        return money;
    }
    public void setMoney(float money) {
        this.money = money;
    }
    @Override
    public String toString() {
        return "Account [id=" + id + ", name=" + name + ", money=" + money
                + "]";
    }
    
}
package com.itheima.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class DBCPUtil {
    private static DataSource dataSource;
    static{
        try {
            InputStream in = DBCPUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
            Properties props = new Properties();
            props.load(in);
            dataSource = BasicDataSourceFactory.createDataSource(props);
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
    
    public static DataSource getDataSource(){
        return dataSource;
    }
    
    public static Connection getConnection(){
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
package com.itheima.dbassist;

import java.sql.ResultSet;

public interface ResultSetHandler {
    /**
     * 把结果中的数据封装到指定的对象中
     * @param rs
     * @return 封装了数据的对象
     */
    Object handle(ResultSet rs);
}
package com.itheima.dbassist;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
 * 封装到JavaBean中
 * 满足约定:数据库字段名和JavaBean字段名保持一致
 * @author wzhting
 *
 */
public class BeanListHanlder implements ResultSetHandler {
    
    private Class clazz;//目标类型
    public BeanListHanlder(Class clazz){
        this.clazz = clazz;
    }

    public Object handle(ResultSet rs) {
        try {
            List list = new ArrayList();
            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);//得到数据库字段名,也就得到了JavaBan的字段名
                    Object fieldValue = rs.getObject(fieldName);//字段值
                    //通过字段反射
                    Field f = clazz.getDeclaredField(fieldName);
                    f.setAccessible(true);
                    f.set(bean, fieldValue);
                }
                list.add(bean);
            }
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
package com.itheima.dbassist;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
/**
 * 适合只有一条查询结果的情况
 * 封装到JavaBean中
 * 满足约定:数据库字段名和JavaBean字段名保持一致
 * @author wzhting
 *
 */
public class BeanHanlder implements ResultSetHandler {
    
    private Class clazz;//目标类型
    public BeanHanlder(Class clazz){
        this.clazz = clazz;
    }

    public Object handle(ResultSet rs) {
        try {
            if(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);//得到数据库字段名,也就得到了JavaBan的字段名
                    Object fieldValue = rs.getObject(fieldName);//字段值
                    //通过字段反射
                    Field f = clazz.getDeclaredField(fieldName);
                    f.setAccessible(true);
                    f.set(bean, fieldValue);
                }
                return bean;
            }
            return null;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
package com.itheima.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 javax.sql.DataSource;

/**
 * 框架的核心类
 * @author wzhting
 *
 */
public class DBAssist {
    private DataSource dataSource;
    public DBAssist(DataSource dataSource){
        this.dataSource = dataSource;
    }
    //写:添加、删除、修改
    //params参数要和sql中的占位符对应
    public void update(String sql,Object...params) {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try{
            conn = dataSource.getConnection();
            stmt = conn.prepareStatement(sql);
            //设置参数
                //得到sql中的参数
                ParameterMetaData pmd = stmt.getParameterMetaData();
                int count = pmd.getParameterCount();
                if(count>0){
                    if(params==null){
                        throw new RuntimeException("必须传入参数的值");
                    }
                    if(count!=params.length){
                        throw new RuntimeException("参数数量不匹配");
                    }
                    for(int i=0;i<count;i++){
                        stmt.setObject(i+1, params[i]);
                    }
                    
                }
            
            stmt.executeUpdate();
        }catch(Exception e){
            throw new RuntimeException(e);
        }finally{
            release(rs, stmt, conn);
        }
    }
    
    
    //读:查询
    public Object query(String sql,ResultSetHandler rsh,Object...params) {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try{
            conn = dataSource.getConnection();
            stmt = conn.prepareStatement(sql);
            //设置参数
                //得到sql中的参数
                ParameterMetaData pmd = stmt.getParameterMetaData();
                int count = pmd.getParameterCount();
                if(count>0){
                    if(params==null){
                        throw new RuntimeException("必须传入参数的值");
                    }
                    if(count!=params.length){
                        throw new RuntimeException("参数数量不匹配");
                    }
                    for(int i=0;i<count;i++){
                        stmt.setObject(i+1, params[i]);
                    }
                    
                }
            
            rs = stmt.executeQuery();
            //有结果集,要封装到对象中。策略设计模式
            return rsh.handle(rs);
        }catch(Exception e){
            throw new RuntimeException(e);
        }finally{
            release(rs, stmt, conn);
        }
    }
    
    
    private 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;
        }
    }
}
package com.itheima.test;

import java.util.List;

import org.junit.Test;

import com.itheima.dbassist.BeanHanlder;
import com.itheima.dbassist.BeanListHanlder;
import com.itheima.dbassist.DBAssist;
import com.itheima.domain.Account;
import com.itheima.util.DBCPUtil;

public class DBAssistTest {
    private DBAssist da = new DBAssist(DBCPUtil.getDataSource());
    @Test
    public void testAdd(){
        da.update("insert into account values (?,?,?)", 7,"ggg",1000);
    }
    @Test
    public void testUpdate(){
        da.update("update account set money=? where id=?", 10000,7);
    }
    @Test
    public void testDel(){
        da.update("delete from account where id=?",7);
    }
    @Test
    public void testQueryOne(){
        Object obj = da.query("select * from account where id=?",new BeanHanlder(Account.class),2);
        System.out.println(obj);
    }
    @Test
    public void testQueryAll(){
        List list = (List)da.query("select * from account",new BeanListHanlder(Account.class));
        for(Object o:list)
            System.out.println(o);
    }
}

 

以上是关于编写JDBC框架:(策略设计模式)的主要内容,如果未能解决你的问题,请参考以下文章

JDBC 学习复习10 编写自己的JDBC框架

JDBC优化策略总结

JDBC-06-笔记

部分代码片段

javaWeb_JDBC_dao模式设计

编写自己的JDBC框架