您的位置:首页 > 编程语言 > Java开发

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

2015-04-02 15:31 861 查看

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>


结果:



资料下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐