数据库_jdbc_连接池

demo1_JDBC演示事务

package cn.itcast.demo;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import cn.itcast.exception.DaoException;
import cn.itcast.utils.JdbcUtils;
public class demo1 {
	public static void main(String[] args) {
		method1();
	}
	private static void method1() {
		/*方法说明:JDBC演示事务!day16库,表account(id,name,money)
		 *id为1的帐户向id为2的帐户转100元*/
		//SQL更新模板代码(sql_u)
	    Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            //因转帐,获得连接后,开启事务
            conn.setAutoCommit(false);//相当于sql中start transaction
            String sql = "update account set money=money-100 where id=?";
            st = conn.prepareStatement(sql);
            st.setInt(1, 1);
            st.executeUpdate();
            //再发第2条sql
            sql = "update account set money=money+100 where id=?";
            st = conn.prepareStatement(sql);
            st.setInt(1, 2);
            st.executeUpdate();
            //出现异常
            int x=1/0;
            //最后提交事务
            conn.commit();
        } catch (Exception e) {
            throw new DaoException(e);
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}


demo2_JDBC演示事务回滚点

package cn.itcast.demo;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;

import cn.itcast.exception.DaoException;
import cn.itcast.utils.JdbcUtils;
public class demo2 {
    public static void main(String[] args) throws SQLException {
        method1();
    }
    private static void method1() throws SQLException {
        /*方法说明:day16库,表account(id,name,money)
         *id为1的帐户向id为2的帐户转100元
         *id为1的帐户向id为3的帐户转100元
         *事务回滚点*/
        //SQL更新模板代码(sql_u)
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        //回滚点!
        Savepoint sp=null;
        try {
            //mysql默认连接的隔离级别:repeatable read(可重复读,即每次读的都一样)
            //属第3种隔离级别,可以预防脏读和不可重复读!
            conn = JdbcUtils.getConnection();
            //因转帐,获得连接后,开启事务
            conn.setAutoCommit(false);//相当于sql中start transaction
            String sql = "update account set money=money-100 where id=?";
            st = conn.prepareStatement(sql);
            st.setInt(1, 1);
            st.executeUpdate();
            //再发第2条sql
            sql = "update account set money=money+100 where id=?";
            st = conn.prepareStatement(sql);
            st.setInt(1, 2);
            st.executeUpdate();
            //设置回滚点,即无论a向c转帐是否成功都尽量确保a向b转帐是成功的!!
            sp=conn.setSavepoint();
            //再发第3条sql
            sql = "update account set money=money-100 where id=?";
            st = conn.prepareStatement(sql);
            st.setInt(1, 1);
            st.executeUpdate();
            //再发第4条sql
            sql = "update account set money=money+100 where id=?";
            st = conn.prepareStatement(sql);
            st.setInt(1, 3);
            st.executeUpdate();
            //出现异常
            int x=1/0;
            //最后提交事务
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
            //出现异常后,手动回滚到指定回滚点,尽量确保a向b转帐是成功的!
            conn.rollback(sp);
            //仅仅是回滚是没用的,必须还要提交事务!
            conn.commit();
            //手动回滚后,一定要记得提交事务
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
        
    }

}



demo3_JDBC演示事务隔离级别

package cn.itcast.demo;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;

import cn.itcast.exception.DaoException;
import cn.itcast.utils.JdbcUtils;
public class demo3 {
    public static void main(String[] args) throws SQLException {
        method1();
    }
    private static void method1() throws SQLException {
        /*方法说明:day16库,表account(id,name,money)
         *简单演示jdbc设置隔离级别*/
        //SQL更新模板代码(sql_u)
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            //mysql默认连接的隔离级别:repeatable read(可重复读,即每次读的都一样)
            //属第3种隔离级别,可以预防脏读和不可重复读!
            conn = JdbcUtils.getConnection();
            //获得连接后,必须先设置好事务隔离级别,再开启事务
            conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
            conn.setAutoCommit(false);//相当于sql中start transaction
            String sql = "select * from account";
            st = conn.prepareStatement(sql);
            st.executeQuery();
            //故意让线程等待10秒!另开一个doc窗口,开启事务进行操作!将出现等待的情况!
            Thread.sleep(1000*10);
            //最后才提交事务
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}



demo4_JDBC演示开源数据库连接池DBCP

package cn.itcast.demo;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import cn.itcast.utils.JdbcUtils_C3P0;
import cn.itcast.utils.JdbcUtils_DBCP;
public class demo4 {
    public static void main(String[] args) throws Exception {
        method1();
    }
    private static void method2() throws SQLException {
        /*方法说明:演示开源数据库连接池DBCP的使用
         *C3P0内部增强Connection的close方法使用的是动态代理拦截技术!*/
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils_C3P0.getConnection();
            System.out.println(conn);
            //com.mchange.v2.c3p0.impl.NewProxyConnection@1049ddf
            System.out.println(conn.getClass().getName());
            //com.mchange.v2.c3p0.impl.NewProxyConnection
        }finally{
            JdbcUtils_DBCP.release(conn, st, rs);
        }
    }
    private static void method1() throws SQLException {
        /*方法说明:演示开源数据库连接池DBCP的使用
         * DBCP内部增强Connection的close方法使用的是装饰模式!*/
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils_DBCP.getConnection();
            System.out.println(conn);
            //jdbc:mysql://localhost:3306/day16, UserName=root@localhost, MySQL-AB JDBC Driver
            System.out.println(conn.getClass().getName());
            //org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper
        }finally{
            JdbcUtils_DBCP.release(conn, st, rs);
        }
    }
}
/*
使用动态代理重写连接池中的Connection 
proxyConn = (Connection) Proxy.newProxyInstance(this.getClass()
            .getClassLoader(), conn.getClass().getInterfaces(),
            new InvocationHandler() {
        //此处为内部类,当close方法被调用时将conn还回池中,其它方法直接执行
            public Object invoke(Object proxy, Method method,
                      Object[] args) throws Throwable {
                if (method.getName().equals("close")) {
                    pool.addLast(conn);
                    return null;
                }
                return method.invoke(conn, args);
            }
    });
*/



demo5_JDBC演示元数据


package cn.itcast.demo;

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 java.sql.SQLException;

import org.junit.Test;

import cn.itcast.utils.JdbcUtils_C3P0;

public class demo5 {
    @Test
    public void method1() throws SQLException {
        /*方法说明:演示获取数据库的元数据 */
        Connection conn=JdbcUtils_C3P0.getConnection();
        DatabaseMetaData meta=conn.getMetaData();
        System.out.println("hello world");
        System.out.println(meta.getDatabaseMajorVersion());//5
        System.out.println(meta.getDatabaseMinorVersion());//0
        System.out.println(meta.getDatabaseProductName());//MySQL
        System.out.println(meta.getDatabaseProductVersion());//5.0.22-community-nt
        System.out.println(meta.getDefaultTransactionIsolation());//2
        System.out.println(meta.getDriverName());//MySQL-AB JDBC Driver
        System.out.println(meta.getDriverVersion());//mysql-connector-java-5.0.8 ( Revision: ${svn.Revision} )
        System.out.println(meta.getDriverMajorVersion());//5
        System.out.println(meta.getDriverMinorVersion());//0
    }
    @Test
    public void method2() throws SQLException   {
        /*方法说明:演示参数元数据*/
        Connection conn=JdbcUtils_C3P0.getConnection();
        String sql="insert into account(id,name,money) values(?,?,?)";
        PreparedStatement st=conn.prepareStatement(sql);
        ParameterMetaData meta=st.getParameterMetaData();
        System.out.println(meta.getParameterCount());//3,其他全部不支持
        /*System.out.println(meta.getParameterClassName(1));
        System.out.println(meta.getParameterMode(1));
        注意:mysql驱动不支持:参数元数据的方法:获取参数类型!
        System.out.println(meta.getParameterType(1));
        System.out.println(meta.getParameterTypeName(1));
        System.out.println(meta.getPrecision(1));*/
        
    }
    @Test
    public void method3() throws SQLException   {
        /*方法说明:演示结果集元数据*/
        Connection conn=JdbcUtils_C3P0.getConnection();
        String sql="select * from account";
        PreparedStatement st=conn.prepareStatement(sql);
        ResultSet rs=st.executeQuery();
        ResultSetMetaData meta=rs.getMetaData();
        System.out.println(meta.getTableName(2));//取表名:account表
        System.out.println(meta.getCatalogName(1));//获取指定列的表目录名称:day16
        System.out.println(meta.getColumnClassName(1));//java.lang.Integer 如果调用方法 ResultSet.getObject 从列中获取值,则返回构造其实例的 Java 类的完全限定名称。
        System.out.println(meta.getColumnCount());//共有三个字段:即列数 3 返回此 ResultSet 对象中的列数。
        System.out.println(meta.getColumnDisplaySize(1));//11 指示指定列的最大标准宽度,以字符为单位。
        System.out.println(meta.getColumnLabel(1));//id 获取用于打印输出和显示的指定列的建议标题。
        System.out.println(meta.getColumnName(1));//id 获取指定列的名称。
        System.out.println(meta.getColumnType(1));//获取指定列的 SQL 类型。来自 java.sql.Types 的 SQL 类型 
        System.out.println(meta.getColumnTypeName(1));//INT 获取指定列的数据库特定的类型名称。 
        System.out.println(meta.getClass());//class com.mysql.jdbc.ResultSetMetaData
        System.out.println(meta.isReadOnly(1));//false
    }
}package cn.itcast.demo;

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 java.sql.SQLException;

import org.junit.Test;

import cn.itcast.utils.JdbcUtils_C3P0;

public class demo5 {
    @Test
    public void method1() throws SQLException {
        /*方法说明:演示获取数据库的元数据 */
        Connection conn=JdbcUtils_C3P0.getConnection();
        DatabaseMetaData meta=conn.getMetaData();
        System.out.println("hello world");
        System.out.println(meta.getDatabaseMajorVersion());//5
        System.out.println(meta.getDatabaseMinorVersion());//0
        System.out.println(meta.getDatabaseProductName());//MySQL
        System.out.println(meta.getDatabaseProductVersion());//5.0.22-community-nt
        System.out.println(meta.getDefaultTransactionIsolation());//2
        System.out.println(meta.getDriverName());//MySQL-AB JDBC Driver
        System.out.println(meta.getDriverVersion());//mysql-connector-java-5.0.8 ( Revision: ${svn.Revision} )
        System.out.println(meta.getDriverMajorVersion());//5
        System.out.println(meta.getDriverMinorVersion());//0
    }
    @Test
    public void method2() throws SQLException   {
        /*方法说明:演示参数元数据*/
        Connection conn=JdbcUtils_C3P0.getConnection();
        String sql="insert into account(id,name,money) values(?,?,?)";
        PreparedStatement st=conn.prepareStatement(sql);
        ParameterMetaData meta=st.getParameterMetaData();
        System.out.println(meta.getParameterCount());//3,其他全部不支持
        /*System.out.println(meta.getParameterClassName(1));
        System.out.println(meta.getParameterMode(1));
        注意:mysql驱动不支持:参数元数据的方法:获取参数类型!
        System.out.println(meta.getParameterType(1));
        System.out.println(meta.getParameterTypeName(1));
        System.out.println(meta.getPrecision(1));*/
        
    }
    @Test
    public void method3() throws SQLException   {
        /*方法说明:演示结果集元数据*/
        Connection conn=JdbcUtils_C3P0.getConnection();
        String sql="select * from account";
        PreparedStatement st=conn.prepareStatement(sql);
        ResultSet rs=st.executeQuery();
        ResultSetMetaData meta=rs.getMetaData();
        System.out.println(meta.getTableName(2));//取表名:account表
        System.out.println(meta.getCatalogName(1));//获取指定列的表目录名称:day16
        System.out.println(meta.getColumnClassName(1));//java.lang.Integer 如果调用方法 ResultSet.getObject 从列中获取值,则返回构造其实例的 Java 类的完全限定名称。
        System.out.println(meta.getColumnCount());//共有三个字段:即列数 3 返回此 ResultSet 对象中的列数。
        System.out.println(meta.getColumnDisplaySize(1));//11 指示指定列的最大标准宽度,以字符为单位。
        System.out.println(meta.getColumnLabel(1));//id 获取用于打印输出和显示的指定列的建议标题。
        System.out.println(meta.getColumnName(1));//id 获取指定列的名称。
        System.out.println(meta.getColumnType(1));//获取指定列的 SQL 类型。来自 java.sql.Types 的 SQL 类型 
        System.out.println(meta.getColumnTypeName(1));//INT 获取指定列的数据库特定的类型名称。 
        System.out.println(meta.getClass());//class com.mysql.jdbc.ResultSetMetaData
        System.out.println(meta.isReadOnly(1));//false
    }
}


demo7_dao演示自定义JDBC框架

package cn.itcast.demo;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
import cn.itcast.domain.Account;
import cn.itcast.utils.BeanHandler;
import cn.itcast.utils.BeanListHandler;
import cn.itcast.utils.IntegerHandler;
import cn.itcast.utils.JdbcUtils;
public class demo7_dao {
    //dao提供方法1:增强一个用户到数据库中!
    public void add(Account a){
        //由于统一了update方法,所以只需要提供sql 和 Object[] params
        String sql="insert into account(name,money) values(?,?)";
        Object[] params={a.getName(),a.getMoney()};
        JdbcUtils.update(sql, params);
    }
    //模拟service层调用dao处理增加业务!
    @Test
    public void test_add(){
        Account a=new Account();
        a.setName("史湘云");
        a.setMoney(1000);
        add(a);
    }
    //====================================
    //dao提供方法2:从数据库中删除一个用户!
    public void delete(String id){
        //由于统一了update方法,所以只需要提供sql 和 Object[] params
        String sql="delete from account where id=?";
        Object[] params={id};
        JdbcUtils.update(sql, params);
    }
    //模拟service层调用dao处理删除业务!
    @Test
    public void test_delete(){
        String id="5";
        delete(id);
    }
    //====================================
    //dao提供方法3:从数据库中改(更新)一个用户!
    public void update(Account a){
        //由于统一了update方法,所以只需要提供sql 和 Object[] params
        String sql="update account set name=?,money=? where id=?";
        Object[] params={a.getName(),a.getMoney(),a.getId()};
        JdbcUtils.update(sql, params);
    }
    //模拟service层调用dao处理更新业务!
    @Test
    public void test_update(){
        Account a=new Account();
        a.setName("史大姑娘");
        a.setMoney(9000);
        a.setId(4);
        update(a);
    }
    //====================================
    //dao提供方法4:从数据库中查找一个用户!
    public Account find(int id){
        //由于统一了query方法,所以只需要提供sql 和 Object[] params 和接口ResultSetHandler的实现类
        //由于是封装到bean里面,所以传需要bean.class字节码文件
        String sql="select * from account where id=?";
        Object[] params={id};
        return (Account) JdbcUtils.query(sql, params,new BeanHandler(Account.class));
    }
    //模拟service层调用dao处理查找一个用户业务!
    @Test
    public void test_findById(){
        int id=3;
        Account a=find(id);
        System.out.println(a.getName());
    }
    //====================================
    //dao提供方法5:从数据库中查找所有用户并存入集合!
    public List<Account> getAll(){
        //由于统一了query方法,所以只需要提供sql 和 Object[] params 和接口ResultSetHandler的实现类
        //由于是封装到bean里面,所以传需要bean.class字节码文件
        String sql="select * from account";
        Object[] params={};
        return (List<Account>) JdbcUtils.query(sql,params, new BeanListHandler(Account.class));
    }
    //模拟service层调用dao处理查找所有用户并存入集合业务!
    @Test
    public void test_getAll(){
        List list=getAll();
        System.out.println(list.size());//3
        System.out.println(list);
        //[cn.itcast.domain.Account@1bb60c3, 
        //cn.itcast.domain.Account@cdb06e, 
        //cn.itcast.domain.Account@1fa1bb6]
    }
    //====================================
    //dao提供方法6:从数据库中统计总记录数!
    public Integer getCountNum(){
        //由于统一了query方法,所以只需要提供sql 和 Object[] params 和接口ResultSetHandler的实现类
        //将查询结果封装到Integer里面
        String sql="select count(*) from account";
        Object[] params={};
        return (Integer) JdbcUtils.query(sql, params, new IntegerHandler());
    }
    //模拟service层调用dao处理统计总记录数业务!
    @Test
    public void test_getCountNum(){
        System.out.println(getCountNum());//4
    }
}



JDBCPool_Demo4演示理论上数据库连接池的实现

package cn.itcast.demo;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.sql.DataSource;
//理论上数据库连接池的实现方式 !
public class JDBCPool_Demo4 implements DataSource {
    private static LinkedList list=new LinkedList<Connection>();
    private static Properties pro=new Properties();
    static{
        //类加载时,就初始化一批连接!
        try {
            pro.load(JDBCPool_Demo4.class.getClassLoader().getResourceAsStream("db.properties"));
            Class.forName(pro.getProperty("driver"));
            //上面一句是注册驱动,之后就可以用驱动管理获取连接!批量
            for (int i = 0; i < 10; i++) {
                Connection conn=DriverManager.getConnection(pro.getProperty("url"), pro.getProperty("user"), pro.getProperty("password"));
                list.add(conn);
            }
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
    //覆写getConnection(),注意不能改变接口的声明!如:随意加static静态代该方法, conn.close()满足不了需求,因为close()默认是将连接释放了,而我们想将连接归还到连接池里面,即list集合中!
    /* 在实际开发,发现对象的方法满足不了开发需求时,有三种方式对其进行增强
     * 1.写一个connecton子类,覆盖close方法,增强close方法
     * 2.用包装设计模式(也称装饰模式)
     * 3.用动态代理    aop 面向切面编程
     */
    @Override
    public Connection getConnection() throws SQLException {
        /*方法说明:首先判断list是不是有Connection
         *然后还要必须保证conn.close()是归还到池子即list,而非释放掉
         */
        if (list.size()<=0) {
            throw new RuntimeException("暂无连接,一会再来");
        }
        /*使用装饰模式,或动态代理,覆写conn.close方法
         * 1,写个类,实现共同的接口
         * 2,该类中定义一个成员,接收被装饰的对象
         * 3,该类中定义一个带参数构造函数,传入的参数即为被装饰的对象
         * 4,增强该增强的方法
         * 5,不要增强的方法使用原来被装饰的对象完成
         */
        //千万不能用list.get(index);返回列表中指定位置的元素。 
        //只是返回对象的引用,而对象仍然在list集合里面!这就不是取出连接了!
        Connection conn=(Connection) list.removeFirst();
        MyColl mycoll=new MyColl(conn);
        return mycoll;
    }
    @Override
    public Connection getConnection(String username, String password)
            throws SQLException {
        return null;
    }
    //使用内部类完成装饰
        //包装设计模式(也称装饰模式)标准5步曲!
        //1.定义一个类(MyConnection),实现与被增强相同的接口(Connection)
        //2.在类中定义一个成员变量,记住被增强对象
        //3.定义一个构造函数,接收被增强对象
        //4.覆盖想增强的方法
        //5.对于不想增强的方法,直接调用目标对象(被增强对象)的方法
    class MyColl implements Connection{
        private Connection conn;
        public MyColl(Connection conn) {
            super();
            this.conn = conn;
        }
        public void close() throws SQLException {
            //增强想增强的方法! 覆写想增强的方法,即原来的满足不了需要的方法!
            list.add(this.conn);
        }
        /*其它不需要增强的方法使用构造时传进来的对象完成即可!
         * 由于方法实在太多,我们就使用开源组织提供的数据库连接池
         * DBCP  database Connection Pool
         * C3P0
         */
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            return this.conn.isWrapperFor(iface);
        }
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            return null;
        }
        @Override
        public void abort(Executor executor) throws SQLException {
        }
        @Override
        public void clearWarnings() throws SQLException {
        }
        @Override
        public void commit() throws SQLException {
        }

        @Override
        public Array createArrayOf(String typeName, Object[] elements)
                throws SQLException {
            return null;
        }

        @Override
        public Blob createBlob() throws SQLException {
            return null;
        }

        @Override
        public Clob createClob() throws SQLException {
            return null;
        }

        @Override
        public NClob createNClob() throws SQLException {
            return null;
        }

        @Override
        public SQLXML createSQLXML() throws SQLException {
            return null;
        }

        @Override
        public Statement createStatement() throws SQLException {
            return null;
        }

        @Override
        public Statement createStatement(int resultSetType,
                int resultSetConcurrency, int resultSetHoldability)
                throws SQLException {
            return null;
        }

        @Override
        public Statement createStatement(int resultSetType,
                int resultSetConcurrency) throws SQLException {
            return null;
        }

        @Override
        public Struct createStruct(String typeName, Object[] attributes)
                throws SQLException {
            return null;
        }

        @Override
        public boolean getAutoCommit() throws SQLException {
            return false;
        }

        @Override
        public String getCatalog() throws SQLException {
            return null;
        }

        @Override
        public Properties getClientInfo() throws SQLException {
            return null;
        }

        @Override
        public String getClientInfo(String name) throws SQLException {
            return null;
        }

        @Override
        public int getHoldability() throws SQLException {
            return 0;
        }

        @Override
        public DatabaseMetaData getMetaData() throws SQLException {
            return null;
        }

        @Override
        public int getNetworkTimeout() throws SQLException {
            return 0;
        }

        @Override
        public String getSchema() throws SQLException {
            return null;
        }

        @Override
        public int getTransactionIsolation() throws SQLException {
            return 0;
        }

        @Override
        public Map<String, Class<?>> getTypeMap() throws SQLException {
            return null;
        }

        @Override
        public SQLWarning getWarnings() throws SQLException {
            return null;
        }

        @Override
        public boolean isClosed() throws SQLException {
            return false;
        }

        @Override
        public boolean isReadOnly() throws SQLException {
            return false;
        }

        @Override
        public boolean isValid(int timeout) throws SQLException {
            return false;
        }

        @Override
        public String nativeSQL(String sql) throws SQLException {
            return null;
        }

        @Override
        public CallableStatement prepareCall(String sql, int resultSetType,
                int resultSetConcurrency, int resultSetHoldability)
                throws SQLException {
            return null;
        }

        @Override
        public CallableStatement prepareCall(String sql, int resultSetType,
                int resultSetConcurrency) throws SQLException {
            return null;
        }

        @Override
        public CallableStatement prepareCall(String sql) throws SQLException {
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql,
                int resultSetType, int resultSetConcurrency,
                int resultSetHoldability) throws SQLException {
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql,
                int resultSetType, int resultSetConcurrency)
                throws SQLException {
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql,
                int autoGeneratedKeys) throws SQLException {
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql,
                int[] columnIndexes) throws SQLException {
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql,
                String[] columnNames) throws SQLException {
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql)
                throws SQLException {
            return null;
        }

        @Override
        public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        }

        @Override
        public void rollback() throws SQLException {
        }

        @Override
        public void rollback(Savepoint savepoint) throws SQLException {
        }

        @Override
        public void setAutoCommit(boolean autoCommit) throws SQLException {
        }

        @Override
        public void setCatalog(String catalog) throws SQLException {
        }

        @Override
        public void setClientInfo(Properties properties)
                throws SQLClientInfoException {
        }

        @Override
        public void setClientInfo(String name, String value)
                throws SQLClientInfoException {
        }

        @Override
        public void setHoldability(int holdability) throws SQLException {
        }

        @Override
        public void setNetworkTimeout(Executor executor, int milliseconds)
                throws SQLException {
        }

        @Override
        public void setReadOnly(boolean readOnly) throws SQLException {
        }

        @Override
        public Savepoint setSavepoint() throws SQLException {
            return null;
        }

        @Override
        public Savepoint setSavepoint(String name) throws SQLException {
            return null;
        }

        @Override
        public void setSchema(String schema) throws SQLException {
        }

        @Override
        public void setTransactionIsolation(int level) throws SQLException {
        }

        @Override
        public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
        }
        
    }
    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }
    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }
    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {
    }
    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
    }
    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }
}



Account位于domain包


package cn.itcast.domain;
public class Account {
    private int id;
    private String name;
    private double 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 double getMoney() {
        return money;
    }
    public void setMoney(double money) {
        this.money = money;
    }
}


DaoException位于exception包

package cn.itcast.exception;

public class DaoException extends RuntimeException {

    public DaoException() {
        // TODO Auto-generated constructor stub
    }

    public DaoException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }

    public DaoException(Throwable cause) {
        super(cause);
        // TODO Auto-generated constructor stub
    }

    public DaoException(String message, Throwable cause) {
        super(message, cause);
        // TODO Auto-generated constructor stub
    }

    

}


ResultSetHandler位于utils包

package cn.itcast.utils;
import java.sql.ResultSet;
//由于拿到了结果集,不知如何处理,即不知道封装到哪儿去!
//所以对外暴露一个接口,由调用该方法的人实现该接口,我再对其调用!策略模式!
public interface ResultSetHandler {
   public Object handle(ResultSet rs);
}


BeanHandler位于utils包

package cn.itcast.utils;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
public class BeanHandler implements ResultSetHandler {
    //该类是将结果集封装到bean里面!
    //为了知道该结果集处理器是将结果封装到哪个bean里面,
    //所以需要一个构造函数接收该bean的字节码文件对象,并赋值给成员!
    private Class clazz;
    public BeanHandler(Class clazz) {
        super();
        this.clazz = clazz;
    }
    public Object handle(ResultSet rs) {
        try {
            //首先分析结果集中有无数据
            if (!rs.next()) {
                return null;
            }
            //然后就准备一个bean实例接收!
            Object bean=clazz.newInstance();
            //获得结果集的元数据
            ResultSetMetaData  meta=rs.getMetaData();
            //从元数据中获得字段的数目
            int count=meta.getColumnCount();
            //循环每个字段,将值赋予给bean对应的成员
            for (int i = 0; i < count; i++) {
                //从元数据中获得字段的名称
                String columnName=meta.getColumnName(i+1);
                //从结果集获得该字段的值
                Object columnValue=rs.getObject(columnName);
                //通过反射,获取所有的类成员
                Field  field=bean.getClass().getDeclaredField(columnName);
                //打开类成员的暴力访问
                field.setAccessible(true);
                //为bean对象的成员赋值
                field.set(bean, columnValue);
            }
            //循环完毕即为bean对象的每个成员赋值!
            return bean;
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
}


BeanListHandler位于utils包

package cn.itcast.utils;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
public class BeanListHandler implements ResultSetHandler {
    //该类是将结果集封装到bean里面,然后把所有的bean加到list集合里面!
    //为了知道该结果集处理器是将结果封装到哪个bean里面,
    //所以需要一个构造函数接收该bean的字节码文件对象,并赋值给成员!
    private Class clazz;
    public BeanListHandler(Class clazz) {
        super();
        this.clazz = clazz;
    }
    public Object handle(ResultSet rs) {
        //先准备一个集合
        List list=new ArrayList();
        try {
            //首先分析结果集中有无数据
            if (!rs.next()) {
                return null;
            }
            //然后遍历每一条记录,将每一条记录封装到一个bean里面,并且bean添加到list
            while (rs.next()) {
                //准备一个bean实例接收一条记录!
                Object bean=clazz.newInstance();
                //获得结果集的元数据
                ResultSetMetaData  meta=rs.getMetaData();
                //从元数据中获得字段的数目
                int count=meta.getColumnCount();
                //循环每个字段,将值赋予给bean对应的成员
                for (int i = 0; i < count; i++) {
                    //从元数据中获得字段的名称
                    String columnName=meta.getColumnName(i+1);
                    //从结果集获得该字段的值
                    Object columnValue=rs.getObject(columnName);
                    //通过反射,获取所有的类成员
                    Field  field=bean.getClass().getDeclaredField(columnName);
                    //打开类成员的暴力访问
                    field.setAccessible(true);
                    //为bean对象的成员赋值
                    field.set(bean, columnValue);
                }
                //循环完毕即为bean对象的每个成员赋值!
                //将封装好了一条记录的bean加到list中!
                list.add(bean);
            }
            //最后,遍历完所有记录后,返回list
            return list;
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
}


IntegerHandler位于utils包

package cn.itcast.utils;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
public class IntegerHandler implements ResultSetHandler {
    //该类是将结果集封装到Integer里面!
    public Object handle(ResultSet rs) {
        try {
            //首先分析结果集中有无数据
            if (!rs.next()) {
                return 0;
            }
            //然后才返回统计数目:如select count(*) from 表名
            return rs.getInt(1);
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
}


JdbcUtils_C3P0位于utils包

package cn.itcast.utils;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**演示开源数据库连接池C3P0的使用
		 C3P0内部增强Connection的close方法使用的是动态代理!
    	1,导入两个jar包到工程下的lib目录,变成奶瓶
       c3p0-0.9.2-pre1.jar
      mchange-commons-0.2.jar
      如果使用oralce数据库,还要c3p0-oracle-thin-extras-0.9.2-pre1.jar
       2,设置src下的c3p0-config.xml配置文件信息如库名!
       3,新建一个工具类如:JdbcUtils_C3P0
       4,定义成员记住C3P0创建出来的数据源(即连接池)
       5,静态代码块中用创建数据源(即连接池)
       6,定义获取连接的方法
       7,定义释放连接的方法
 */
public class JdbcUtils_C3P0 {
   //定义成员记住DBCP创建出来的数据源(即连接池)
   private static DataSource ds;
   static{
      try {
        //C3P0连接池--固定代码:
         //new ComboPooledDataSource创建数据源(即连接池)
          //用类成员ds记住根据参数(空参表示使用c3p0默认的配置)创建出来的连接池!
         //new的时候不指定参数,则使用的是default配置!否则使用指定名称配置,
         //如"mysql",具体名称见c3p0-config.xml
         ds=new ComboPooledDataSource();
         //ds=new ComboPooledDataSource("mysql");
         //然后自动搜索类目录下名为:c3p0-config.xml的文件进行初始化!
      } catch (Exception e) {
         throw new ExceptionInInitializerError(e);
      }
   }
   //方法1:获取使用了动态代理的连接
   public static Connection getConnection() throws SQLException{
      //C3P0在生成连接的时候已经使用动态代理拦截Connection名为close的方法,
      //并覆写了close方法,即归还到数据源(即连接池)
      //返回的是NewProxyConnection
      return ds.getConnection();
   }
   //方法2:释放连接
     public static void release(Connection conn,Statement st,ResultSet rs){
       if (conn!=null) {
         try {
           conn.close();
         }catch (Exception e) {
           //只能记录!一旦抛出,后面的2条if代码就无法执行了
           e.printStackTrace();
         }
         conn=null;
       }
       if (st!=null) {
         try {
           st.close();
         }catch (Exception e) {
           //只能记录!一旦抛出,后面的1条if代码就无法执行了
           e.printStackTrace();
         }
         st=null;
       }
       if (rs!=null) {
         try {
           rs.close();
         }catch (Exception e) {
           e.printStackTrace();
         }
         rs=null;
       }
     }
}


JdbcUtils_DBCP位于utils包

package cn.itcast.utils;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
/**演示开源数据库连接池DBCP的使用
        DBCP内部增强Connection的close方法使用的是装饰模式!
       1,导入两个jar包到工程下的lib目录,变成奶瓶
       commons-dbcp-1.2.2.jar
       commons-pool.jar
       2,设置src下的dbcpconfig.properties配置文件信息如库名!
       3,新建一个工具类如:JdbcUtils_DBCP
       4,定义成员记住DBCP创建出来的数据源(即连接池)
       5,静态代码块中用BasicDataSourceFactory创建数据源(即连接池)
       6,定义获取连接的方法
       7,定义释放连接的方法
 */
public class JdbcUtils_DBCP {
   //定义成员记住DBCP创建出来的数据源(即连接池)
   private static DataSource ds;
   static{
      try {
         String pro_name="dbcpconfig.properties";
          InputStream in=JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream(pro_name);
          Properties pro = new Properties();
          pro.load(in);
        //DBCP连接池--固定代码:由工厂创建数据源(即连接池)
          BasicDataSourceFactory factory=new BasicDataSourceFactory();
          //用类成员记住根据配置文件创建出来的连接池!
          ds=factory.createDataSource(pro);
      } catch (Exception e) {
         throw new ExceptionInInitializerError(e);
      }
   }
   //方法1:获取已装饰的连接
   public static Connection getConnection() throws SQLException{
      //DBCP在生成连接的时候已经装饰过Connection,
      //覆写了close方法,即归还到数据源(即连接池)
      return ds.getConnection();
   }
   //方法2:释放连接
     public static void release(Connection conn,Statement st,ResultSet rs){
       if (conn!=null) {
         try {
           conn.close();
         }catch (Exception e) {
           //只能记录!一旦抛出,后面的2条if代码就无法执行了
           e.printStackTrace();
         }
         conn=null;
       }
       if (st!=null) {
         try {
           st.close();
         }catch (Exception e) {
           //只能记录!一旦抛出,后面的1条if代码就无法执行了
           e.printStackTrace();
         }
         st=null;
       }
       if (rs!=null) {
         try {
           rs.close();
         }catch (Exception e) {
           e.printStackTrace();
         }
         rs=null;
       }
     }
}


JdbcUtils_Old位于utils包

package cn.itcast.utils;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JdbcUtils_Old {
  private static Properties pro=new Properties();
  /*
   * 静态成员Properties
   * 静态代码块:加载配置文件,注册驱动
   * 静态方法1:获取连接
   * 静态方法2:释放连接
   * 工具类的异常只管抛,也可以转型后抛
   * db.properties文件位于类目录下即src
   */
  static{
    String pro_name="db.properties";
    InputStream in=JdbcUtils_Old.class.getClassLoader().getResourceAsStream(pro_name);
    try {
      pro.load(in);
      Class.forName(pro.getProperty("driver"));
    } catch (Exception e) {
      // 静态代码块的异常只能转型后抛出
      throw new ExceptionInInitializerError(e);
    }
  }
  //方法1:获取连接
  public static Connection getConnection() throws SQLException{
    String url=pro.getProperty("url");
    String user=pro.getProperty("user");
    String password=pro.getProperty("password");
    Connection conn=DriverManager.getConnection(url, user, password);
    return conn;
  }
  //方法2:释放连接
  public static void release(Connection conn,Statement st,ResultSet rs){
    if (conn!=null) {
      try {
        conn.close();
      }catch (Exception e) {
        //只能记录!一旦抛出,后面的2条if代码就无法执行了
        e.printStackTrace();
      }
      conn=null;
    }
    if (st!=null) {
      try {
        st.close();
      }catch (Exception e) {
        //只能记录!一旦抛出,后面的1条if代码就无法执行了
        e.printStackTrace();
      }
      st=null;
    }
    if (rs!=null) {
      try {
        rs.close();
      }catch (Exception e) {
        e.printStackTrace();
      }
      rs=null;
    }
  }
}


JdbcUtils位于utils包

package cn.itcast.utils;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

import cn.itcast.exception.DaoException;
/**利用开源数据库连接池DBCP,创建自己的JDBC框架!
DBCP内部增强Connection的close方法使用的是装饰模式!
1,导入两个jar包到工程下的lib目录,变成奶瓶
commons-dbcp-1.2.2.jar
commons-pool.jar
2,设置src下的dbcpconfig.properties配置文件信息如库名!
3,定义静态成员DataSource记住DBCP创建出来的数据源(即连接池)
4,静态代码块中用BasicDataSourceFactory创建数据源(即连接池)
5,定义获取连接的方法
6,定义释放连接的方法
7,定义统一的update方法(增删改)
8,定义统一的查询方法(使用策略设计模式)*/
public class JdbcUtils {
   //定义成员记住DBCP创建出来的数据源(即连接池)
  private static DataSource ds;
  static{
      try {
         String pro_name="dbcpconfig.properties";
          InputStream in=JdbcUtils.class.getClassLoader().getResourceAsStream(pro_name);
          Properties pro = new Properties();
          pro.load(in);
        //DBCP连接池--固定代码:由工厂创建数据源(即连接池)
          BasicDataSourceFactory factory=new BasicDataSourceFactory();
          //用类成员记住根据配置文件创建出来的连接池!
          ds=factory.createDataSource(pro);
      } catch (Exception e) {
         throw new ExceptionInInitializerError(e);
      }
   }
  //方法1:从连接池中获取已装饰过的连接
  public static Connection getConnection() throws SQLException{
        //DBCP在生成连接的时候已经装饰过Connection,
      //覆写了close方法,即归还到数据源(即连接池)
      return ds.getConnection();
  }
  //方法2:释放连接标准步骤!
  public static void release(Connection conn,Statement st,ResultSet rs){
    if (conn!=null) {
      try {
        conn.close();
      }catch (Exception e) {
        //只能记录!一旦抛出,后面的2条if代码就无法执行了
        e.printStackTrace();
      }
      conn=null;
    }
    if (st!=null) {
      try {
        st.close();
      }catch (Exception e) {
        //只能记录!一旦抛出,后面的1条if代码就无法执行了
        e.printStackTrace();
      }
      st=null;
    }
    if (rs!=null) {
      try {
        rs.close();
      }catch (Exception e) {
        e.printStackTrace();
      }
      rs=null;
    }
  }
  //方法3:定义统一的update方法(增删改)
  public static void update(String sql,Object[] params){
     Connection conn = null;
      PreparedStatement st = null;
      ResultSet rs = null;      
      try{
         conn = JdbcUtils.getConnection();
         st = conn.prepareStatement(sql);       
         //应该分情况讨论:参数数组为null或空,直接执行sql
         if(params==null || params.length==0){
            st.executeUpdate();
            return;
         }
         //否则用参数数组替换掉sql中的所有问号!
         for(int i=0;i<params.length;i++){
         //第1个参数是1,第2个参数是2,依此类推
         st.setObject(i+1,params[i]);
       }
       //替换完毕,执行完整的sql语句(增删改)
         st.executeUpdate();
      }catch (Exception e) {
         throw new DaoException(e);
      }finally{
         JdbcUtils.release(conn, st, rs);
      }
  }
  //方法4:定义统一的query方法(查询)
  public static Object query(String sql,Object[] params,ResultSetHandler rsh){
     Connection conn = null;
      PreparedStatement st = null;
      ResultSet rs = null;      
      try{
         conn = JdbcUtils.getConnection();
         st = conn.prepareStatement(sql);       
         //应该分情况讨论:只有参数数组不为null或长度不为0,才进行参数替换!
         if(params!=null || params.length!=0){
            //用参数数组替换掉sql中的所有问号!
            for(int i=0;i<params.length;i++){
               //第1个参数是1,第2个参数是2,依此类推
               st.setObject(i+1,params[i]);
            }
         }
         //替换完毕,执行完整的sql语句(查询)
         rs=st.executeQuery();
         //我拿到结果不知道怎么处理,于是采用策略模式:
         //对外暴露一个ResultSetHandler接口,由调用该方法的人实现接口,
         //我再对其调用,将人家处理后的结果返回!
         return rsh.handle(rs);
      }catch (Exception e) {
         throw new DaoException(e);
      }finally{
         JdbcUtils.release(conn, st, rs);
      }
  }
}


c3p0-config.xml位于src类目录下

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
	<!--前面四个默认没有,自己对着文档加上的-->
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property>
		<property name="user">root</property>
		<property name="password">root</property>
		<!--maxIdleTime单位是秒!-->
		<property name="maxIdleTime">30</property>
		<property name="acquireIncrement">5</property>
		<property name="initialPoolSize">10</property>
      <property name="minPoolSize">5</property>
      <property name="maxPoolSize">20</property>
   </default-config>
      <named-config name="flx">
      <property name="driverClass">com.mysql.jdbc.Driver</property>
      <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property>
      <property name="user">root</property>
      <property name="password">root</property>
      <property name="acquireIncrement">5</property>
      <property name="initialPoolSize">10</property>
      <property name="minPoolSize">5</property>
      <property name="maxPoolSize">20</property>
   </named-config>
   <named-config name="mysql">
      <property name="acquireIncrement">50</property>
      <property name="initialPoolSize">100</property>
      <property name="minPoolSize">50</property>
      <property name="maxPoolSize">1000</property>
      <!-- intergalactoApp adopts a different approach to configuring statement caching -->
      <property name="maxStatements">0</property>
      <property name="maxStatementsPerConnection">5</property>
   </named-config>
   <named-config name="oracle">
      <property name="acquireIncrement">50</property>
      <property name="initialPoolSize">100</property>
      <property name="minPoolSize">50</property>
      <property name="maxPoolSize">1000</property>
      <!-- intergalactoApp adopts a different approach to configuring statement caching -->
      <property name="maxStatements">0</property>
      <property name="maxStatementsPerConnection">5</property>
   </named-config>
</c3p0-config>


dbcpconfig.properties位于src类目录下

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day16
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 即等1分钟后仍没连接,这时才告诉人家,呆会再来,暂无连接! -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] 
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=utf8
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_COMMITTED


用到的第3方jar包

mysql-connector-java-5.0.8-bin.jar
commons-dbcp-1.2.2.jar
commons-pool.jar
c3p0-0.9.2-pre1.jar
c3p0-oracle-thin-extras-0.9.2-pre1.jar
mchange-commons-0.2.jar



























你可能感兴趣的:(jdbc,c3p0,数据库连接池,DBCP)