JavaWeb-16 JDBC编程进阶(自定义数据源+开源数据源:DBCP、C3P0)

2023-10-27

JavaWeb-16

JDBC编程进阶(自定义数据源+开源数据源:DBCP、C3P0)

一、调用存储过程

a、存储过程是什么?

将一组SQL组合在一起,类似于java代码里面的函数
现实当中SQL命令不可能一条一条调用。
目的为了打包存储调用。
放在服务器上,已经编译好。
买烟的例子(一次买一根还是买一包?)

b、代码:如何操作?

这些代码可以用java代码类比。
在代码框架里可以调用多行sql语句。
在代码中可以定义结束符号。
以后接触需要输入代码的机会少,因为别人需要程序员做的就是提供给程序员接口,给过程输入代码。

二、批处理

Statement和PreparedStatement都可以做批量处理

首先使用Statement来处理:Statement中的addBatch()方法:用来放入批量SQL语句

然后执行呢?executeBatch()方法批量执行

最后clearBatch(),清空此Statement对象的当前SQL命令列表

这是整个处理流程。

使用Statement实现批处理的特点

1、可以执行不同的sql语句
2、但参数是必须确定的

使用PreparedStatement实现

特点:执行的SQL相同,但参数不同,通常用于批量添加,或删除。

三、事务

1、事务的概念:事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。

2、用sql语言怎么控制事务?

例如:A——B转帐,对应于如下两条sql语句

update account set money=money-100 where name=‘a’;
update account set money=money+100 where name=‘b’;

最后确然语句是否成立?

rollback;//该句让以上的语句无效,即不提交

那么如何提交?

commit();

数据库开启事务命令DTL

start transaction  开启事务
Rollback  回滚事务
Commit   提交事务

3、那么在jdbc中怎么控制事务的?

利用prepareStatement来编程

st = con.prepareStatement("update account set money = money-? where id = ?");
st.setInt(1,100);
st.setInt(2,1);

int i  =  1/0;//为了抛出异常,去执行回滚            

st.executeUpdate();
st = con.prepareStatement("update account set money = money+? where id = ?");
st.setInt(1,100);
st.setInt(2,2);

st.executeUpdate();

以上如何开事务?

查文档:Connection去找开启事务的方法

setAutoCommit()

在以上代码前开启事务:

con.setAutoCommit(false);//不自动提交,开启事务

如没有问题,就在代码最后提交事务:

con.commit();

如果有问题,

那么就在就在catch(Exception e){con.rollback();}//因为如果以上代码异常了,那么con.commit()也执行不了了。

如果以上代码不加事务机制,那么会怎样?

那么会-100的代码执行了,而+100的代码没执行,因为有异常。所以该处能体现事务机制的好处

4、事务的特性和隔离级别(必须清楚:数据安全):涉及多线程

多线程同时操作同一事务。引起操作数据冲突。

那么事务有什么特性呢?

a.原子性:处于同一个事务中的多条语句,要么全都成功,要么全都不成成功。
b.一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账:转账前a+b=2000,转账后a+b=2000
c.隔离性:多线程并发时,一个事务不能被其他事务所干扰。
d.持久性:数据应该被永久性的保存起来。(硬盘,而不是内存)

如果不考虑事务的隔离性,会导致以下不正确的问题:

a、脏读:指一个事务读到了另外一个事务中未提交的数据
b、不可重复读:指一个事务读到了另外一个事务update后(事务提交了)的数据
c、虚读:指一个事务读到了另外一个事务insert的数据

数据库有四个隔离级别:

READ UNCOMMITTED:脏读、不可重复读、虚读都有可能发生。
READ COMMITTED:防止脏读发生;不可重复读、虚读都有可能发生。
REPEATABLE READ:(MySQL默认级别)防止脏读、不可重复读;虚读有可能发生。
SERIALIZABLE:防止脏读、不可重复读、虚读的发生

特点:从上到下,隔离级别越高,数据越安全,但是效率越低

在SQL中如何输入代码?

select @@tx_isolation;        查看当前数据库的隔离级别
set transaction  isolation  level 四个级别之一;更改当前事务的隔离级别
各种不同的数据库的默认隔离级别不一样。

实验:项目架构:day1600procedure


jdbccfg.properties


TestBatch.java

package com.itheima.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

import com.itheima.utils.JdbcUtil;

public class TestBatch {

    public static void main(String[] args) {
        //testBatch1();
        //testBatch2();
        testBatch3();
    }

    private static void testBatch3() {
        Connection con = null;
        PreparedStatement st = null;
        try {
            con = JdbcUtil.getConnection();
            st = con.prepareStatement("insert into usersw values(?,?)");
            //使用PreparedStatement实现批处理特点:  1.可以执行相同的SQL语句,2.但参数是不同的,通常用于实现批量添加,或删除
           for (int i = 0; i <38; i++) {//这是个坑
             st.setInt(1, i+100);
             st.setString(2, "aj"+i);

             //用于将参数加入到批处理命令中
             st.addBatch();

             if(i%10==0){
                 st.executeBatch();
                 st.clearBatch();
             }
           }

            //2.执行批处理
            st.executeBatch();
            //3.清空命令列表
            st.clearBatch();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            JdbcUtil.release(null, st, con);
        }
    }

    private static void testBatch2() {
        Connection con = null;
        PreparedStatement st = null;
        try {
            con = JdbcUtil.getConnection();
            st = con.prepareStatement("insert into usersw values(?,?)");
            //使用PreparedStatement实现批处理特点:  1.可以执行相同的SQL语句,2.但参数是不同的,通常用于实现批量添加,或删除
           for (int i = 0; i <10000000; i++) {//这是个坑
             st.setInt(1, i+10);
             st.setString(2, "aj"+i);

             //用于将参数加入到批处理命令中
             st.addBatch();
           }

            //2.执行批处理
            st.executeBatch();
            //3.清空命令列表
            st.clearBatch();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            JdbcUtil.release(null, st, con);
        }
    }
    private static void testBatch1() {
        Connection con = null;
        Statement st = null;
        try {
            con = JdbcUtil.getConnection();
            st = con.createStatement();
            //使用Statement实现批处理特点:  1.可以执行不同的SQL语句,2.但参数是必须确定的
            st.addBatch("create table usersw(id int primary key,name varchar(20))");
            st.addBatch("insert into usersw values(1,'cgx')");
            st.addBatch("update usersw set name='aj' where id=1");


            //2.执行批处理
            st.executeBatch();
            //3.清空命令列表
            st.clearBatch();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally{
            JdbcUtil.release(null, st, con);
        }
    }

}

TestProcedure.java

package com.itheima.test;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;

import com.itheima.utils.JdbcUtil;

public class TestProcedure {

    //CallableStatement专用于执行过程,它是PreparedStatement的子类
    public static void main(String[] args) {
        Connection con = null;
        CallableStatement st = null;
        try {
            con = JdbcUtil.getConnection();
            st = con.prepareCall("{call demoSp(?,?)}");//用于调用存储过程
            st.setString(1, "cgx");
            st.registerOutParameter(2, Types.VARCHAR);//用于注册输出参数

            st.execute();//不能用executeUpdate(),executeQuery()
            String result = st.getString(2);//获取第二个输出参数的值
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtil.release(null, st, con);
        }
    }

}

TestTransaction.java

package com.itheima.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.itheima.utils.JdbcUtil;

public class TestTransaction {

    //转账操作
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement st = null;

        try {
            con = JdbcUtil.getConnection();
            //先设置事务隔离级别,再开启事务
            con.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
            //1.开启事务
            con.setAutoCommit(false);//不自动提交,事务已开启
            st = con.prepareStatement("update account set money=money-? where id=?");
            st.setInt(1, 100);
            st.setInt(2, 1);

            st.executeUpdate();


            int i=1/0;

            //2.第二个步骤
            st = con.prepareStatement("update account set money=money+? where id=?");
            st.setInt(1, 100);
            st.setInt(2, 2);

            st.executeUpdate();

            con.commit();//事务提交
            con.setAutoCommit(true);//更新事务模式,一条语句就是一个事务
        } catch (Exception e) {
            e.printStackTrace();
            if(con!=null){
                try {
                    //事务回滚
                    con.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
        }finally{
            JdbcUtil.release(null, st, con);
        }
    }

}

IDGenerator.java

package com.itheima.utils;

import java.util.UUID;

public class IDGenerator {

    public static String genID(){
        return UUID.randomUUID().toString();//Mac+随机数
    }
}

JdbcUtil.java

package com.itheima.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 JdbcUtil {

    private static String DRIVER ;
    private static String URL;
    private static String USER;
    private static String PASSWORD;

    static{
        InputStream is =JdbcUtil.class.getClassLoader().getResourceAsStream("jdbccfg.properties");
        Properties p = new Properties();
        try {
            p.load(is);
            DRIVER = p.getProperty("driver");
            URL = p.getProperty("url");
            USER = p.getProperty("user");
            PASSWORD = p.getProperty("password");

            Class.forName(DRIVER);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到连接
     * @throws SQLException 
     *
     */
    public static Connection getConnection() throws SQLException{
        return DriverManager.getConnection(URL,USER,PASSWORD);
    }

    /**
     * 关闭资源
     */
    public static void release(ResultSet rs,Statement st,Connection con){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            st = null;
        }

        if(con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            con = null;
        }
    }

}

结果:

dos输入测试过程的代码:


过程测试结果:


批处理结果:


测试事务:


四、自定义数据源

问题:数据库不用了,直接关闭了。

没有自定义数据源的弊端:


自定义数据源的优势:


为了连接数据库的桥梁不要每次都彻底关闭,而是存起来以备下次使用

1.自定义数据源的优点?

就是更好的利用数据库连接,用完后放回到数据库连接池中,从而提高连接的使用率。

实验:

a.自定义连接池
b.对已知类的已知方法(不能改源码),改变它的原有功能(改实现)

目前改写com.mysql.jdbc.Connection.close();让他不要关闭链接,而是还回池中。在自定义的数据库连接池里的方法myds.close(con);但是程序员习惯会con.close();这样写代码,这样会让原来的数据库连接池的方法是去了意义,那么我们需要改写Connection类底层的close()方法。让他的功能和myds.close(con)一样。

接下来引出包装设计模式的使用

继承:子类可以覆盖父类的方法(不靠谱)

包装(装饰)设计模式

口诀:
    1、编写一个类,实现与被包装类相同的接口
    2、定义一个变量,记住被包装类对象的引用
    3、定义构造方法,传入被包装类对象
    4、对于要改变的方法,书写你的代码即可
    5、对不需要要改变的方法,用原有对象的
    (似你、还有你、拜托你、改写你。)

默认适配器设计模式

动态代理(很重要。AOP面向切面编程)

总结:(必须知道)

1、日后尽量使用标准的数据源(一般都带有连接池),为的就是提高效率
2、当用户调用Connection.close()方法,并不能关闭链接,而是还回池中

但是我们练习这不是为了自己建立数据池,而是调用别人的标准数据池:DataSource接口。数据工厂:以此代替JDBCUtils。sun公司提供的数据源的接口规范:javax.sql.DataSource;

实验:项目/day1602mydatasource:

项目架构:


jdbccfg.properties


MySimpleDataSource.java

package com.itheima.datasource;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.itheima.utils.JdbcUtil;

public class MySimpleDataSource {

    //1.内部维护一个池
    private static List<Connection> pool = new ArrayList<Connection>();
    private static int size=10;//初始化时连接的个数
    public void setSize(int size) {
        this.size = size;
    }

    //2.初始化池,放入一系列数据库连接
    static {
        try {
            for (int i = 0; i <size; i++) {
                Connection con = JdbcUtil.getConnection();
                pool.add(con);
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化连接池失败");
        }
    }

    //3.取连接
    public synchronized Connection getConnection(){
        if(pool.size()>0){
            Connection con = pool.remove(0);
            MyConnection1 myconn1 = new MyConnection1(con,pool);

            return myconn1;
        }else{
            throw new RuntimeException("获取连接池失败");
        }
    }

    //4.还回池中
    public void close(Connection con){
        pool.add(con);
    }

    //返回池对象
    public List<Connection >getPool(){
        return pool;
    }

}

MyConnection.java

    package com.itheima.datasource;

    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.NClob;
    import java.sql.PreparedStatement;
    import java.sql.SQLClientInfoException;
    import java.sql.SQLException;
    import java.sql.SQLWarning;
    import java.sql.SQLXML;
    import java.sql.Savepoint;
    import java.sql.Statement;
    import java.sql.Struct;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;

    /**
     * @author wangli
     *利用包装设计模式,包装了Connection,改写它的close()
     */
    public class MyConnection1 implements Connection{
        private Connection con;
        private List<Connection > pool;

        public MyConnection1(Connection con ,List<Connection> pool){
            this.con  = con;
            this.pool =pool;
        }


        @Override
        public void close() throws SQLException {
            this.pool.add(con);//收回到池中
        }
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public Statement createStatement() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public CallableStatement prepareCall(String sql) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public String nativeSQL(String sql) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void setAutoCommit(boolean autoCommit) throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public boolean getAutoCommit() throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void commit() throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public void rollback() throws SQLException {
            // TODO Auto-generated method stub

        }


        @Override
        public boolean isClosed() throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public DatabaseMetaData getMetaData() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void setReadOnly(boolean readOnly) throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public boolean isReadOnly() throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void setCatalog(String catalog) throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public String getCatalog() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void setTransactionIsolation(int level) throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public int getTransactionIsolation() throws SQLException {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        public SQLWarning getWarnings() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void clearWarnings() throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public Statement createStatement(int resultSetType, int resultSetConcurrency)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql, int resultSetType,
                int resultSetConcurrency) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public CallableStatement prepareCall(String sql, int resultSetType,
                int resultSetConcurrency) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Map<String, Class<?>> getTypeMap() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public void setHoldability(int holdability) throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public int getHoldability() throws SQLException {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        public Savepoint setSavepoint() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Savepoint setSavepoint(String name) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void rollback(Savepoint savepoint) throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public void releaseSavepoint(Savepoint savepoint) throws SQLException {
            // TODO Auto-generated method stub

        }

        @Override
        public Statement createStatement(int resultSetType,
                int resultSetConcurrency, int resultSetHoldability)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql, int resultSetType,
                int resultSetConcurrency, int resultSetHoldability)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public CallableStatement prepareCall(String sql, int resultSetType,
                int resultSetConcurrency, int resultSetHoldability)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public PreparedStatement prepareStatement(String sql, String[] columnNames)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Clob createClob() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Blob createBlob() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public NClob createNClob() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public SQLXML createSQLXML() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public boolean isValid(int timeout) throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void setClientInfo(String name, String value)
                throws SQLClientInfoException {
            // TODO Auto-generated method stub

        }

        @Override
        public void setClientInfo(Properties properties)
                throws SQLClientInfoException {
            // TODO Auto-generated method stub

        }

        @Override
        public String getClientInfo(String name) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Properties getClientInfo() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Array createArrayOf(String typeName, Object[] elements)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Struct createStruct(String typeName, Object[] attributes)
                throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }

    }

ConnectionAdapter.java

package com.itheima.datasource;

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.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;

//适配器
public class ConnectionAdapter implements Connection {

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public Statement createStatement() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean getAutoCommit() throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void commit() throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public void rollback() throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public void close() throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean isClosed() throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean isReadOnly() throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public String getCatalog() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public int getTransactionIsolation() throws SQLException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void clearWarnings() throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType,
            int resultSetConcurrency) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType,
            int resultSetConcurrency) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public void setHoldability(int holdability) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public int getHoldability() throws SQLException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public Statement createStatement(int resultSetType,
            int resultSetConcurrency, int resultSetHoldability)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType,
            int resultSetConcurrency, int resultSetHoldability)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType,
            int resultSetConcurrency, int resultSetHoldability)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Clob createClob() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Blob createBlob() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public NClob createNClob() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void setClientInfo(String name, String value)
            throws SQLClientInfoException {
        // TODO Auto-generated method stub

    }

    @Override
    public void setClientInfo(Properties properties)
            throws SQLClientInfoException {
        // TODO Auto-generated method stub

    }

    @Override
    public String getClientInfo(String name) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Properties getClientInfo() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

}

MyConnection2

package com.itheima.datasource;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

//包装设计模式
public class MyConnection2 extends ConnectionAdapter {
    private Connection con;
    private List<Connection > pool;

    public MyConnection2(Connection con ,List<Connection> pool){
        this.con  = con;
        this.pool =pool;
    }

    @Override
    public void close() throws SQLException {
        this.pool.add(con);//收回到池中
    }
}

MyDataSource1.java

package com.itheima.datasource;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import com.itheima.utils.JdbcUtil;
//为了自定义数据源能更好的被其它人使用,也要求自定义数据源实现SUN公司提供的标准接口DataSource
public class MyDataSource1 implements DataSource {
    //1.内部维护一个池
        public static List<Connection> pool = new ArrayList<Connection>();
        private static int size=10;//初始化时连接的个数
        public void setSize(int size) {
            this.size = size;
        }

        //2.初始化池,放入一系列数据库连接
        static {
            try {
                for (int i = 0; i <size; i++) {
                    Connection con = JdbcUtil.getConnection();
                    pool.add(con);
                }
            } catch (Exception e) {
                throw new RuntimeException("初始化连接池失败");
            }
        }

    @Override
    public Connection getConnection() throws SQLException {
        if(pool.size()>0){
            Connection con = pool.remove(0);
            /*MyConnection1 myconn1 = new MyConnection1(con,pool);

            return myconn1;*/
            //真正的包装
            MyConnection2 myconn2 = new MyConnection2(con,pool);
            return myconn2;
        }else{
            throw new RuntimeException("获取连接池失败");
        }
    }



    @Override
    public PrintWriter getLogWriter() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }



    @Override
    public Connection getConnection(String username, String password)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

}

MyDataSource2.java

package com.itheima.datasource;

import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import com.itheima.utils.JdbcUtil;
//为了自定义数据源能更好的被其它人使用,也要求自定义数据源实现SUN公司提供的标准接口DataSource
public class MyDataSource2 implements DataSource {
    //1.内部维护一个池
        public static List<Connection> pool = new ArrayList<Connection>();
        private static int size=10;//初始化时连接的个数
        public void setSize(int size) {
            this.size = size;
        }

        //2.初始化池,放入一系列数据库连接
        static {
            try {
                for (int i = 0; i <size; i++) {
                    Connection con = JdbcUtil.getConnection();
                    pool.add(con);
                }
            } catch (Exception e) {
                throw new RuntimeException("初始化连接池失败");
            }
        }

    @Override
    public Connection getConnection() throws SQLException {
        if(pool.size()>0){
            final Connection con = pool.remove(0);

            //动态代理
            //loader :代表类加载器   ,被代理的对象con用什么类加载器,代理对象就用什么类加载器
            //interfaces:代表所实现的接口,  被代理的对象con实现什么接口,代理对象就实现什么接口
            Connection proxyConn = (Connection)Proxy.newProxyInstance(con.getClass().getClassLoader(), con.getClass().getInterfaces(), 
                    new InvocationHandler() {
                      //策略模式
                        public Object invoke(Object proxy, Method method, Object[] args)
                                throws Throwable {
                            if("close".equals(method.getName())){
                                return pool.add(con);
                            }else{
                                //对于其它方法,原来怎么调用,现在还怎么调用,不改写 
                                return method.invoke(con, args);
                            }

                        }
                    }
                    );
            return proxyConn;
        }else{
            throw new RuntimeException("获取连接池失败");
        }
    }



    @Override
    public PrintWriter getLogWriter() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }



    @Override
    public Connection getConnection(String username, String password)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

}

JText.java

package com.itheima.test;

import java.sql.Connection;
import java.sql.SQLException;

import org.junit.Test;

import com.itheima.datasource.MySimpleDataSource;

public class JTest {

    @Test
    public void test1() throws Exception{
        MySimpleDataSource myds = new MySimpleDataSource();
        System.out.println("初始化时池中连接个数"+myds.getPool().size());

        //取一个连接
        Connection con = myds.getConnection();
        System.out.println(con);
        //code...    con.createStatement();
        System.out.println("取走一个连接,但没有还:"+myds.getPool().size());

        //3.还回到池中
        //myds.close(con);
        con.close();

        //con.close();//大多数程序员会使用con.close()来实现连接关闭?????-------->要改写close()方法让它也把连接还回池中
        System.out.println("还回后,连接个数:"+myds.getPool().size());
    }
}

JTest2.java

package com.itheima.test;

import java.sql.Connection;

import javax.sql.DataSource;

import org.junit.Test;

import com.itheima.datasource.MyDataSource1;

public class JTest2 {
    @Test
    public void test1() throws Exception{
        DataSource myds = new MyDataSource1();
        //System.out.println("初始化时池中连接个数"+MyDataSource1.pool.size());

        //取一个连接
        Connection con = myds.getConnection();
        System.out.println(con);
        //code...    con.createStatement();
        //System.out.println("取走一个连接,但没有还:"+MyDataSource1.pool.size());

        //3.还回到池中
        con.close();

        //System.out.println("还回后,连接个数:"+MyDataSource1.pool.size());
    }
}

JTest.java

package com.itheima.test;

import java.sql.Connection;

import javax.sql.DataSource;

import org.junit.Test;

import com.itheima.datasource.MyDataSource2;

public class JTest3 {
    @Test
    public void test1() throws Exception{
        DataSource myds = new MyDataSource2();
        //System.out.println("初始化时池中连接个数"+MyDataSource2.pool.size());

        //取一个连接
        Connection con = myds.getConnection();
        System.out.println(con);
        //code...    con.createStatement();
        //System.out.println("取走一个连接,但没有还:"+MyDataSource2.pool.size());

        //3.还回到池中
        con.close();

        //System.out.println("还回后,连接个数:"+MyDataSource2.pool.size());
    }
}

IDGenerator.java

package com.itheima.utils;

import java.util.UUID;

public class IDGenerator {

    public static String genID(){
        return UUID.randomUUID().toString();//Mac+随机数
    }
}

JdbcUtil.java

package com.itheima.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 JdbcUtil {

    private static String DRIVER ;
    private static String URL;
    private static String USER;
    private static String PASSWORD;

    static{
        InputStream is =JdbcUtil.class.getClassLoader().getResourceAsStream("jdbccfg.properties");
        Properties p = new Properties();
        try {
            p.load(is);
            DRIVER = p.getProperty("driver");
            URL = p.getProperty("url");
            USER = p.getProperty("user");
            PASSWORD = p.getProperty("password");

            Class.forName(DRIVER);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到连接
     * @throws SQLException 
     *
     */
    public static Connection getConnection() throws SQLException{
        return DriverManager.getConnection(URL,USER,PASSWORD);
    }

    /**
     * 关闭资源
     */
    public static void release(ResultSet rs,Statement st,Connection con){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            st = null;
        }

        if(con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            con = null;
        }
    }

}

结果:

JTest测试结果:MySimpleDataSource.java+MyConnection1.java


JTest2测试:MyConnection2.java+ConnectionAdapter.java


JTest3测试:MyDataSource2.java


/day1602mydatasource攻略:

涉及程序ConnectionAdapter.java、MyConnection1.java、MyConnection2.java、MySimpleDataSource.java、JTest.java,这些程序间存在什么联系呢?

首先新建一个MySimpleDataSource.java,来演示数据库连接池的原理,用来解决客户端向服务器获取连接服务量过多导致服务器处理不过来的问题:在MySimpleDataSource.java里,通过new一个List集合用来存储静态代码块生成的默认的连接服务资源Connection,并提供方法让客户端来获取集合里的Connection资源但是,老师从一个方面引出了该连接服务资源的弊端,就是程序员有可能直接在使用从该类中获得的Connection时去调用Connection类的底层close()方法,那么Connection就没有被回收到MySimpleDataSource.java类里而被系统回收了,那么还是解决不了服务器处理不过来的问题,那么怎么解决该问题呢?老师通过新建MyConnection1.java,然后直接实现Connection接口,并把接口里的方法全部实现了,并把个别Connection接口的底层方法接口给改变了功能,例如
    @Override
    public void close() throws SQLException {
        this.pool.add(con);//收回到池中
    }

这样修改了之后,在MySimpleDataSource.java在把原来初始化生成的Connection资源传到MyConnection1.java类进行加工,MyConnection1.java把Connection资源的底层代码进行装饰加工,并返回给MySimpleDataSource.java,那么程序员即使是调MySimpleDataSource.java本来的close方法还是继承过来的底层close方法,都不用担心,这就是类包装方法的雏形。但是问题来了,我们不可能在每次要解决该类问题时都要新建MyConnection1.java这样的类,并把实现的所有方法给实现一遍。所以我们就借助适配器这程序:所谓适配器就是新建一个类ConnectionAdapter.java,去实现Connection接口,并把所有方法都实现了,然后我们如果要给MySimpleDataSource.java的资源进行装饰,就直接继承ConnectionAdapter.java适配器,直接找你需要修改的底层方法拿出来进行修改就好了,然后MySimpleDataSource.java直接调用继承了适配器的java类就OK,就可以方便使用到装饰过的Connection资源。也就是MyDataSource1.java利用MyConnection2.java类来装饰类Connection资源。

MySimpleDataSource.java攻略:

该类主要使用到的工具有:实现了SUN公司提供的标准接口DataSource+动态代理类的使用。对于SUN公司提供的标准接口DataSource和我们之前学习的MyConnection1.java实现Connection接口获得连接资源一样,现在SUN公司提供给我们的接口更加符合程序员平时编程时习惯和使用风格,那么我们以后再学习JDBC编程的时候,就不要再用旧的方法获去连接资源了,就直接实现SUN公司的DataSource接口就好,至于在MySimpleDataSource.java    里出现了动态代理类的作用,就是用来更高效率地代替之前实例中的装饰类的作用。在MySimpleDataSource.java的getConnection方法里,当获得了Connection资源后,就可通过动态代理类来获取Connection连接资源的底层方法接口,然后程序员可以根据自己的需要去选择要使用到的底层方法接口,并在动态代理类里实现方法接口,以此代替装饰类的作用。其实,动态代理类也是一个特殊的装饰类。

MyDataSource1.java:

实现sun公司的标准接口把里面为实现的接口getConnection的接口实现功能,其他就包装出去。为了自定义数据源能更好的被其他人使用,也要求自定义数据源实现SUN公司以后做连接,我们需要实现该接口后去获得连接,所以我们以前获得连接的方法就放弃好了真正的包装不是包MyConnection1,而是包装MyConnection2


自定义数据源只是为了让我们了解开源数据源的的原理。

五、开源的数据源

现在很多WEB服务器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的实现,即连接池的实现。通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。

也有一些开源组织提供了数据源的独立实现:

1、DBCP 数据库连接池

DBCP 是 Apache 软件基金组织下的开源连接池实现,使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:

    Commons-dbcp.jar:连接池的实现
    Commons-pool.jar:连接池实现的依赖库

Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。

实验:项目:day1603dbcp

项目架构:


dbcpcfg.properties


DbcpUtil.java

package com.itheima.utils;

import java.io.IOException;
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;

public class DbcpUtil {
    private static DataSource ds;
    static{
        try {
            InputStream is = DbcpUtil.class.getClassLoader().getResourceAsStream("dbcpcfg.properties");
            Properties p = new Properties();
            p.load(is);

            //生成数据源
            ds = BasicDataSourceFactory.createDataSource(p);
        } catch (Exception e) {
            throw new RuntimeException("加载数据源失败");
        }


    }

    /**
     * 获取数据库连接
     * @return
     * @throws Exception
     */
    public static Connection getConnection() throws Exception{
        return ds.getConnection();
    }

    public static DataSource getDataSource(){
        return ds;
    }

    /**
     * 关闭资源
     */
    public static void release(ResultSet rs,Statement st,Connection con){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            st = null;
        }

        if(con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            con = null;
        }
    }
}

JTest.java

package com.itheima.test;

import java.sql.Connection;
import java.sql.Statement;

import org.junit.Test;

import com.itheima.utils.DbcpUtil;

public class JTest {

    @Test
    public void testAdd(){
        Connection con = null;
        Statement st = null;

        try {
            con = DbcpUtil.getConnection();//从连接池中取一个连接
            st = con.createStatement();
            st.executeUpdate("insert into usersw values(2,'姚钟武')");
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            DbcpUtil.release(null, st, con);
        }
    }
}

JTest前


JTest后


2、C3P0 数据库连接池

实际应用时不需要编写连接数据库代码,直接从数据源获得数据库的连接。程序员编程时也应尽量使用这些数据源的实现,以提升程序的数据库访问性能。

C3P0数据源:怎么用呢?封装C3P0工具类来使用

然后查文档如何获取连接?QuickStart中介绍

private DataSource ds = new ComboPooledDataSource();
ds.getConnection();

推荐使用C3P0数据源!!!普遍公司使用

Tomcat已经把DBCP整合到里面了。

实验:项目:day1604C3P0

项目架构:


c3p0-config.xml

<?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/day15</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>
    </default-config>

    <named-config name="mysql">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/day15</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="oracle">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/day15</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>
</c3p0-config>

C3P0Util.java

package com.itheima.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0Util {

    private static  DataSource ds = new ComboPooledDataSource();
    /**
     * 获取数据库连接
     * @return
     * @throws Exception
     */
    public static Connection getConnection() throws Exception{
        return ds.getConnection();
    }

    public static DataSource getDataSource(){
        return ds;
    }

    /**
     * 关闭资源
     */
    public static void release(ResultSet rs,Statement st,Connection con){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            st = null;
        }

        if(con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            con = null;
        }
    }
}

JTest.java

package com.itheima.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

import com.itheima.utils.C3P0Util;

public class JTest {
      @Test
      public void testUpdate(){
          Connection con = null;
          PreparedStatement st = null;
          String sql= "update usersw set name=? where id=?";
          try {
            con = C3P0Util.getConnection();
              st = con.prepareStatement(sql);
              st.setString(1, "钟武与高富帅的故事");
              st.setInt(2, 2);

              st.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            C3P0Util.release(null, st, con);
        }
      }
}

JTest前


JTest后


3、JNDI技术简介

JNDI(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.naming包,

这套API的主要作用在于:它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需通过名称检索即可。

其核心API为Context,它代表JNDI容器,其lookup方法为检索容器中对应名称的对象。

使用JNDI编程:Tomcat在启动时就用DBCP绑定到JNDI这名字上。其实绑定的是一个连接池的对象。那么我们就要知道Tomcat安装到了什么位置?都是阿帕奇的产品

所以在tomcat里的lib都包括了DBCP的jar包,所以我们只需要把mysql的jar拖到lib下配置好tomcat服务器。

总结:我所理解的开源的数据源,就是实现了sun公司的标准接口DataSource后,实现接口的所有方法,并提供给用户/程序员来调用,不同开源产品之间调用的方式会有小小差别,但不阻碍程序员的使用效率。

实验:项目:day1605jndi

项目架构:


JNDIUtil.java

package com.itheima.utils;

import java.sql.Connection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class JNDIUtil {

    /**
     * @param args
     */
    public static Connection getConnection() {
        try {
            Context initCtx = new InitialContext();//初始化上下文
            //"java:comp/env"代表java的计算机环境    通过JNDI从Tomcat容器中加载出DataSource对象
            DataSource ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/EmployeeDB");
            //DataSource ds =(DataSource) envCtx.lookup("jdbc/EmployeeDB");
            Connection con = ds.getConnection();
            return con;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取连接失败");
        }

    }

}

在使用jndi是要把sql的连接jar包放入到tomcat的lib文件夹下


在IE输入地址


利用Jsp页面输出到服务器con资源信息


六、反射出数据库的元信息、

数据库元信息:描述数据库信息的信息

Connection------->用的是什么数据库产品,什么数据库版本

Parameter:代表?

ResultSet:----->推出列名,列数

用这些来做自定义数据库框架。

需要规范: 程序员的存在就是因为有规范,程序员根据规范来编程 原则:约定由于编码。

如何得到数据库中的源数据?

1、元数据- DataBaseMetaData

元数据:数据库、表、列的定义信息。

Connection.getMetaData()
DataBaseMetaData对象
getURL():返回一个String类对象,代表数据库的URL。
getUserName():返回连接当前数据库管理系统的用户名。
getDatabaseProductName():返回数据库的产品名称。
getDatabaseProductVersion():返回数据库的版本号。
getDriverName():返回驱动驱动程序的名称。
getDriverVersion():返回驱动程序的版本号。
isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。

2、元数据- ParameterMetaData

PreparedStatement . getParameterMetaData() 
获得代表PreparedStatement元数据的ParameterMetaData对象。 
Select * from user where name=? And password=?
ParameterMetaData对象
getParameterCount() 
获得指定参数的个数
getParameterType(int?param) 
获得指定参数的sql类型(驱动可能不支持)

3、元数据- ResultSetMetaData

ResultSet. getMetaData() 
获得代表ResultSet对象元数据的ResultSetMetaData对象。 
ResultSetMetaData对象
getColumnCount() 
返回resultset对象的列数
getColumnName(int?column) 
获得指定列的名称
getColumnTypeName(int?column)
获得指定列的类型 java.sql.Types

实验:项目:day1606metadata

项目架构:


ServletDemo1.java

package com.itheima.servlet;

import java.io.IOException;
import java.io.PrintWriter;
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 javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itheima.utils.C3P0Util;

public class ServletDemo1 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        //testDatabaseMetaData(out);


        //testParameterMetaData(out);

        testResultSetMetaData(out);

    }

    //结果集元信息
        private void testResultSetMetaData(PrintWriter out) {
            try {
                Connection con = C3P0Util.getConnection();
                PreparedStatement st = con.prepareStatement("select * from usersw");
                ResultSet rs = st.executeQuery();

                //得到结果集元数据
                ResultSetMetaData rsmd = rs.getMetaData();

                //得到列数
                int count = rsmd.getColumnCount();
                for (int i = 0; i < count; i++) {
                    //得到第i+1列的列名
                    String columnName = rsmd.getColumnName(i+1);
                    String columnType = rsmd.getColumnTypeName(i+1);

                    out.write("列名:"+columnName+",列的类型:"+columnType);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    //参数元信息
    private void testParameterMetaData(PrintWriter out) {
        try {
            Connection con = C3P0Util.getConnection();
            PreparedStatement st = con.prepareStatement("insert into usersw values(?,?)");
            //PreparedStatement st = con.prepareStatement("??????");
            //得到参数元数据
            ParameterMetaData pmd = st.getParameterMetaData();
            int count = pmd.getParameterCount();//得到?的个数
            out.write("?号的个数是:"+count);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //数据库元信息
    private void testDatabaseMetaData(PrintWriter out) {
        try {
            Connection con = C3P0Util.getConnection();
            //得到数据库的元数据
            DatabaseMetaData dmd = con.getMetaData();
            out.write("数据库产品名:"+dmd.getDatabaseProductName()+"<br>");
            out.write("数据库版本:"+dmd.getDatabaseProductVersion());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);

    }

}

C3P0Util.java

package com.itheima.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0Util {

    private static  DataSource ds = new ComboPooledDataSource();
    /**
     * 获取数据库连接
     * @return
     * @throws Exception
     */
    public static Connection getConnection() throws Exception{
        return ds.getConnection();
    }

    public static DataSource getDataSource(){
        return ds;
    }

    /**
     * 关闭资源
     */
    public static void release(ResultSet rs,Statement st,Connection con){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            st = null;
        }

        if(con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            con = null;
        }
    }
}

c3p0-config.xml

<?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/day15</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>
    </default-config>

    <named-config name="mysql">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/day15</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="oracle">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/day15</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>
</c3p0-config>

结果:



资料下载

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaWeb-16 JDBC编程进阶(自定义数据源+开源数据源:DBCP、C3P0) 的相关文章

  • JSP&EL表达式&MVC&三层结构综合案例

    文章目录 JSP 1 JSP 概述 2 JSP 快速入门 2 1 搭建环境 2 2 导入 JSP 依赖 2 3 创建 jsp 页面 2 4 编写代码 2 5 测试 3 JSP 原理 4 JSP 脚本 4 1 JSP 脚本分类 4 2 案例
  • Servlet与Jsp之间有哪些数据传输的方式?

    前言 根据MVC架构大家都很清楚 servlet充当咱们mvc中的c 也就是controller 而jsp则是咱们的view 所以呀 根据它们各自的职责划分 servlet相当于是一个指挥官 将页面数据交给业务逻辑层去处理 处理后的数据也就
  • 详解Java四大作用域

    文章目录 四大作用域 1 pageContext 1 1定义 2 request 详解 2 1定义 2 2 request域对象的使用 2 3生命周期 2 4 获取请求头数据 3 session 详解 3 1定义 3 2 获取session
  • Idea的 Cannot resolve method ‘getAttribute(java.lang.String)‘问题解决

    问题 写javaweb jsp时使用application getAttribute出现报错 Cannot resolve method getAttribute java lang String 解决方法 第一步 File gt Proj
  • 重新学javaweb---ServletContext

    WEB容器在启动时 它会为每个WEB应用程序都创建一个对应的ServletContext对象 它代表当前web应用 这个对象创建出来之后就一直在内存中驻留 代表当前的web应用 它可以通过我们上一篇介绍的ServletConfig对象获取
  • JavaWeb——JavaWeb核心之Servlet

    一 Servlet简介 1 什么是Servlet Servlet 运行在服务端的Java小程序 是sun公司提供一套规范 接口 用来处理客户端请求 响应给浏览器的动态资源 但servlet的实质就是java代码 通过java的API 动态的
  • JDBC讲解

    SUN公司于1996年提供了一套访问数据库的标准Java类库 即JDBC 一 什么是JDBC JDBC的全称是Java数据库连接 Java Database Connectivity 它是一套用于执行SQL语句的Java API 应用程序可
  • Web后端开发(请求响应)上

    请求响应的概述 浏览器 请求 lt HTTP协议 gt 响应 Web服务器 请求 获取请求数据 响应 设置响应数据 BS架构 浏览器 服务器架构模式 客户端只需要浏览器 应用程序的逻辑和数据都存储在服务端 维护方便 体验一般 CS架构 客户
  • Springboot 实现发送邮件功能,使用QQ邮箱

    引入依赖
  • 前端三剑客---HTML&CSS&JavaScript

    HTML CSS JavaScript 1 HTML 1 1 介绍 1 2 快速入门 1 3 基础标签 1 3 1 标题标签 1 3 2 hr标签 1 3 3 字体标签 1 3 4 换行标签 1 3 5 段落标签 1 3 6 加粗 斜体 下
  • 利用MVC做一个 常见的管理系统

    登陆的部分 gt 数据库 gt 表 admin id name pass regtime 表与类的映射关系 基于面向对象 转换成对象的操作 gt 登陆页面
  • JavaWeb购物商城

    系统前台 前台用户操作 账号 test密码 test 登录页面 商品浏览 商品详情 购物车 订单页面 系统后台 后台用户操作 账号 admin密码 admin 用户登录页面 后台主页 添加商品 编辑商品 删除商品 数据库 部分代码 logi
  • 如何访问WEB-INF文件夹下的jsp文件

    我们都知道不能直接访问WEB INF文件夹下的jsp文件 那应该怎样访问呢 首先 WEB INF目录是Java WEB应用的安全目录 客户端无法访问 只有服务端可以访问 然后 为什么要这么设计 这样做的初衷是在WEB INF文件夹下放一些不
  • Shell中的幽灵王者—JAVAWEB 内存马 【认知篇】

    Goby社区第 21 篇技术分享文章 全文共 6700 字 预计阅读时间 17 分钟 自我介绍 大家好 我是 su18 无论是个人博客还是社区 已经很久没写技术文章了 原因有很多 时间 精力 心态等等 但在开源社区也算比较活跃 由于工作需要
  • spring的jdbcTemplate批量添加数据,单条数据中文正常,多数据第二条数据开始中文乱码

    今天用spring的jdbcTemplate org springframework jdbc core JdbcTemplate 批量添加数据 方法是jdbcTemplate bathUpdate 然后遇到一个很神奇的问题 批量添加的数据
  • shell脚本中$#、$*、$@、$?、$0-n等含义一次性搞明白!!!

    一 Shell脚本变量的含义 1 表示执行脚本传入参数的个数 2 表示执行脚本传入参数的列表 不包括 0 3 表示进程的id Shell本身的PID ProcessID 即脚本运行的当前 进程ID号 4 Shell最后运行的后台Proces
  • JavaWeb —— AJAX

    目录 AJAX 基本介绍 A synchronous JavaScript And XML 多用在 1浏览器搜索联想 2用户注册中离开光标 校验数据的正确性 同步和异步的区别 AJAX快速入门 AJAX 基本介绍 A synchronous
  • 解决Jenkins插件不能下载安装的问题

    安装到这一步 显示无法下载Jenkins插件 安装中升级站点 如果你还在安装过程中 遇见这个问题 你可以打开一个新的网页 输入网址http localhost 8080 pluginManager advanced 在最下面的升级站点 把其
  • form表单中使用fileUpLoad上传文件

    在最近的项目中 需要对用户的头像就行上传 这里了解到使用appche的 大家可自行到mvn库搜索jar包名进行下载 这里需要注意的是代码中对参数的读取 正常情况下我么使用getparameter方法进行读取表单数据 但是因为在form中我们
  • 【封装】实体类(entity)

    实体类entity 一 ORM 1 1 ORM 实体类 entity 零散数据的载体 1 1 1 ORM应用 一 ORM ORM Object Relational Mapping 从数据库查询到的结果集 ResultSet 在进行遍历时

随机推荐

  • 彻聊DNS

    先得聊聊什么是域名 域名是什么 我会连域名都不知道 别着急 先看看嘛 我们以www fanyi baidu com为例 域名结构划分为根域名 顶级域名 二级域名 三级域名等 做过开发的都知道 在创建项目时 一般是com xxx xxx 这就
  • 【毕业设计】大数据用户画像数据分析系统 - python

    文章目录 1 前言 2 用户画像分析概述 2 1 用户画像构建的相关技术 2 2 标签体系 2 3 标签优先级 3 实站 百货商场用户画像描述与价值分析 3 1 数据格式 3 2 数据预处理 3 3 会员年龄构成 3 4 订单占比 消费画像
  • 设计模式之单例模式(通俗易懂,超详细)

    1 什么是单例模式 单例模式 属于创建类型的一种常用的软件设计模式 通过单例模式的方法创建的类在当前进程中只有一个实例 根据需要 也有可能一个线程中属于单例 如 仅线程上下文内使用同一个实例 百度百科 简单来说单例模式就是指在内存中只会创建
  • 简单几个配置 Go 实现敏感数据脱敏,可以自定义数据脱敏规则(附完整实现源码)

    简单几个配置 Go 实现敏感数据脱敏 可以自定义数据脱敏规则 附完整实现源码 介绍 为了保障企业的数据安全和隐私安全 godlp 提供了一系列针对敏感数据的识别和处置方案 其中包含敏感数据识别算法 数据脱敏处理方式 业务自定义的配置选项和海
  • c当中宏理解

    宏 Macro 是预处理命令的一种 它允许用一个标识符来表示一个字符串 include
  • STM32F429配置MircoPython的SDRAM参数

    本例使用的开发板是正点原子STM32F429 一 修改mpconfigboard h文件 具体配置如下 SDRAM define MICROPY HW SDRAM SIZE 32 1024 1024 32M Bytes define MIC
  • 拉格朗日对偶

    https www cnblogs com ooon p 5723725 html
  • Ngrok 服务搭建

    一 前言 ngrok 是一个反向代理 通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道 ngrok 可捕获和分析所有通道上的流量 便于后期分析和重放 ngrok一条命令可以解决外网访问内网问题 本地WEB外网访问 本地开发
  • Nginx的安装(Ubuntu)以及常用简介

    目录 Nginx安装 安装前提 源码下载 Nginx安装方式 简单说明nginx目录下的内容 Nginx编译和安装 启动 Nginx安装 安装前提 gcc pcre库 函数库 支持解析正则表达式 apt get install libpcr
  • 快速学习Stm32舵机控制板控制一个舵机运动

    PWM是什么 PWM 英文名Pulse Width Modulation 是脉冲宽度调制缩写 它是通过对一系列脉冲的宽度进行调制 等效出所需要的波形 包含形状以及幅值 对模拟信号电平进行数字编码 也就是说通过调节占空比的变化来调节信号 能量
  • 域名到站点的负载均衡技术一览

    一 问题域 nginx lvs keepalived f5 DNS轮询 往往讨论的是接入层的这样几个问题 1 可用性 任何一台机器挂了 服务受不受影响 2 扩展性 能否通过增加机器 扩充系统的性能 3 反向代理 负载均衡 请求是否均匀分摊到
  • QComboBox样式表 下拉框 QSS 样式表

    注意 QComboBox pComboBox new QComboBox this pComboBox gt setView new QListView 添加这句 设置下拉列表项高才能生效 未下拉时 QComboBox的样式 QComboB
  • Kubernetes下载kube-flannel失败解决方案 大数据

    Kubernetes下载kube flannel失败解决方案 大数据 Kubernetes是一个开源的容器编排平台 而kube flannel是Kubernetes集群中广泛使用的网络插件 用于提供容器之间的网络互通 然而 有时候在下载ku
  • Socket通讯工具类【SocketTools】(20140402修订版)

  • error pulling image configuration: Get https://production.cloudflare.docker.com/registry-v2/docker/

    error pulling image configuration Get https production cloudflare docker com registry v2 docker 原因 使用docker拉取镜像失败 解决方法 在
  • socket 网络通信 ( windows + Linux )

    参考 C socket 网络通信等 Socket 编程 socket起源于Unix 而Unix Linux基本哲学之一就是 一切皆文件 都可以用 打开open gt 读写write read gt 关闭close 模式来操作 Socket就
  • springboot 连接数据库失败取消自动重试,DruidDataSource取消自动重试

    默认是无限自动重试 导致程序卡死 那么如果我不想让它重试呢 方案1 application properties里面添加即可 spring datasource druid break after acquire failure true
  • java接口菱形继承

    其实菱形继承的副作用只是因为公共基类的成员变量 Java的接口可以做出类似菱形继承的结构 但因为公共基类 接口 中没有成员变量 所以没有二义性问题啦 当然也可以使用内部类 嵌套类 来实现类似多继承 不必担心会发生钻石危机 因为用内部类实现多
  • VScode自动生成项目结构树

    1 安装插件 project tree 2 使用 Shift Cmd p或者F1 输入 Project Tree 3 结果自动生成在README md文件中 exampleObject gitignore babel config js p
  • JavaWeb-16 JDBC编程进阶(自定义数据源+开源数据源:DBCP、C3P0)

    JavaWeb 16 JDBC编程进阶 自定义数据源 开源数据源 DBCP C3P0 一 调用存储过程 a 存储过程是什么 将一组SQL组合在一起 类似于java代码里面的函数 现实当中SQL命令不可能一条一条调用 目的为了打包存储调用 放