总结JDBC相关东西和思路,用以回头查看。
—————————————分割线———————————————
一、最原始的连接数据库方式
首先来看一段最原始的连接数据库的方法:不实用JDBC,直接使用Oracle的java驱动去连接。
package com.lj95801.cla1;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import org.junit.Test;
public class testConnection_1 {
@Test
public void test1() throws SQLException{
//1. 创建一个 Driver 实现类的对象(Oracle实现)
Driver driver = new oracle.jdbc.driver.OracleDriver();
//2. 准备连接数据库的基本信息: url, user, password
String url = "jdbc:oracle:thin:@localhost:1521:orcl";
Properties info = new Properties();
info.put("user", "SCOTT");
info.put("password", "tiger");
//3. 调用 Driver 接口的 connect(url, info) 获取数据库连接
Connection connection = driver.connect(url, info);
System.out.println(connection);
}
}
我们可以总结出:
要操作数据库,首先必须要得到数据库的连接Connection类的一个引用,否则什么事情都干不了。
怎么得到这个Connection引用呢?
每个数据库(Oracle,MySQL等)都会实现Java的一个接口:Driver,而在这个接口的实现类中都会提供一个connect方法。通过 "driver.connect(...)" 的方式就能够得到这个数据库的连接。
想要连接数据库至少要向connect方法中传入三样东西:url(数据库在什么位置)、user(用户名)、password(密码)。
所以,上面的代码就很明了了。
2、我需要通用性
现在的状况是这样的:
①我可能会将数据库由MySQL升级到Oracle,那么我就要修改Driver驱动;
②我的密码可能要不定时的修改,那么我就要修改password;
③我的数据库可能要放在其他的服务器上面去,那么我就要修改url。
困难的是,这些信息可能散布在工程文件的各个部分。因此,修改及其困难。所以,将上面的代码修改成以下的方式:
package com.lj95801.cla1;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;
import org.junit.Test;
public class testConnection_1 {
/**
* 编写一个通用的方法, 在不修改源程序的情况下, 可以获取任何数据库的连接
* 解决方案: 把数据库驱动 Driver 实现类的全类名、url、user、password 放入一个
* 配置文件中, 通过修改配置文件的方式实现和具体的数据库解耦.
* @throws Exception
*/
public Connection getConnection() throws Exception{
String driverClass = null;
String jdbcUrl = null;
String user = null;
String password = null;
//1、读取类路径下的 jdbc.properties 文件,获得具体driver实现类和三样东西。
InputStream in =
this.getClass().getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
properties.load(in);
driverClass = properties.getProperty("driver");
jdbcUrl = properties.getProperty("jdbcUrl");
user = properties.getProperty("user");
password = properties.getProperty("password");
//2、通过反射创建Driver 对象.
Driver driver =
(Driver) Class.forName(driverClass).newInstance();
Properties info = new Properties();
info.put("user", user);
info.put("password", password);
//3、通过 Driver 的 connect 方法获取数据库连接.
Connection connection = driver.connect(jdbcUrl, info);
in.close();
return connection;
}
@Test
public void test2() throws Exception{
Connection connect = getConnection();
System.out.println(connect);
}
}
jdbc.properties的内容如下:
driver=oracle.jdbc.driver.OracleDriver
jdbcUrl=jdbc:oracle:thin:@localhost:1521:orcl
user=scott
password=tiger
这样做的好处就是:getConnection函数不和任何具体的数据库驱动耦合。我只是在jdbc.properties文件中读取必要的信息,然后进行连接得到connection。并且,所有的连接都读取这个文件中的内容。所以,无论你是要升级数据库也好,还是要修改用户和密码都只需要在jdbc.properties文件中集中修改。
这样代码就具有了一定的通用性。
下面先按照使用的逻辑先介绍一些常用和重要的接口和方法。实际上,使用JDBC就是使用下面这些相关的接口。因为这是java定义的接口标准,所以想要支持java操作的数据库都要实现这些必要的接口。我们编程的时候用接口标准的方法来操作,那么代码就具有了可移植性。
Connection接口中有以下常用的方法:
/*最终的SQL查询要归结到Statement或PreparedStatement上面来*/
Statement createStatement();
/*比上面这个要常用*/
PreparedStatement prepareStatement(String sql);
void close();
boolean isClosed();
/*和事物相关的,主要是有三个*/
void setAutoCommit(boolean autoCommit); //设置为false,取消自动提交
void commit(); //事物都处理完了,没有异常,则提交
void rollback(); //事物处理途中出现了异常,则要回滚到初始状态,通常放在catch语句中
/*以下两个参考使用*/
void rollback(Savepoint savepoint);
Savepoint setSavepoint();
PreparedStatement接口中的常用方法有:
</pre><pre name="code" class="java">void setObject(int parameterIndex, Object x); //给sql语句的占位符填充内容
/*执行查询或者是更新的命令*/
ResultSet executeQuery(); //执行查询,需要返回查询结果
int executeUpdate(); //执行和更新相关的SQL语句,如:INSERT, UPDATE or DELETE
void setBlob(int parameterIndex, Blob x); //比如说在数据库中插入图片
/*积累sql语句,当达到多少条以后一次性发送给数据库执行,可以提高效率*/
void addBatch();
int[] executeBatch();
ResultSet接口的实现类存放查询返回的结果,其中有如下常用的方法:
</pre><pre name="code" class="java">/*得到游标指示当前行的 列索引或者是列名 的值*/
Object getObject(String columnLabel);
Object getObject(int columnIndex);
/*ResultSetMetaData中存放了和返回结果的列相关的信息,比如列数目,列名等*/
ResultSetMetaData getMetaData();
/*移动游标相关的操作,最初状态是:指针指向结果第一行的前面,相当于beforefirst*/
boolean next(); //游标向后移动一个位置,如果移动以后指示的一行是有数据的就返回true,如果没有返回false
boolean first(); //将游标移动到第一行,如果有数据返回true,没有但会false
void beforeFirst() //将游标移动到第一行前面的位置,相当于初始状态
ResultSetMetaData接口中定义了如下的一些常用方法:
</pre><pre name="code" class="java">int getColumnCount(); //获取总的列数
String getColumnLabel(int column); //获取列索引值的别名(SQL语句中可以起别名)
String getColumnName(int column) //获取列索引值的本名
—————————— 准备工作 ——————————————
到目前为止,我们可以获得数据库的连接了。下面介绍如何利用这个连接来执行增、删、改、查的操作。首先看一看数据库表单customers的设计:
再看一看Student类,后面所有的实例都使用这个类:
</pre><pre name="code" class="java">package com.lj95801.cla1;
import java.util.List;
import com.lj95801.utils.JDBCDAO;
public class Student {
private int id;
private String name;
private String email;
public Student() {
super();
}
public Student(int id, String name, String email) {
super();
this.id = id;
this.name = name;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", email=" + email
+ "]";
}
}
下面介绍一个工具:BeanUtils。
可以用这个类的静态方法很方便的设置其它类的属性值:
<pre name="code" class="java"><pre name="code" class="java">
@Testpublic void testBeanUtils() throws IllegalAccessException, InvocationTargetException{Student student = new Student();BeanUtils.setProperty(student, "id", 1234567); //设置id属性值BeanUtils.setProperty(student, "name", "李雷"); //设置name属性值System.out.println(student);}
执行结果:
可以看出,其不用调用student的setXxx()方法就能够设置成功。
但是,其有特殊要求:BeanUtils.setProperty(student, "name", "李雷"),实际上它会调用student.setName("李雷")来执行初始化的。所以,Student类必须有对应的set方法,而且setXxx中的Xxx是BeanUtils.setProperty第二个参数首字母大写以后得到的。
也就是说,比如要BeanUtils.setProperty(student, "name", "李雷")能够成功调用,则Student中必须要有setName(String name)方法(注意:set后的第一个字母大写)但是方法中对谁赋值无关紧要。
———————————— 具体方法介绍 ——————————
其中的增、删、改操作不涉及到数据的返回和处理,所以可以归结到一起来处理,下面的update方法可以完成:
</pre><pre name="code" class="java">/**
* 更新。可处理的操作有:更新,删除,插入三种操作。
*
* @param connection
* @param sql
* @param objects
*/
public static void update(Connection connection, String sql,
Object... objects) {
PreparedStatement preStatement = null;
try {
// 1、通过connection得到preStatement,它可以为sql占位符填充内容,防止sql注入
preStatement = connection.prepareStatement(sql);
// 2、for循环为sql语句填充占位符
for (int i = 0; i < objects.length; i++) {
preStatement.setObject(i + 1, objects[i]);
}
// 3、调用executeUpdate()方法执行更新
preStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 4、释放资源
release(null, preStatement, null, null);
}
}
如何使用以上的方法呢?看下面的例子:
<pre name="code" class="java"><pre name="code" class="java">
package com.lj95801.cla1;import java.sql.Connection;import org.junit.Test;import com.lj95801.utils.JDBCDAO;import com.lj95801.utils.JDBCTools;public class TestJDBCDAO {@Testpublic void testUpdate() throws Exception{String sql = null;//获得connectionConnection connection = JDBCTools.getConnection("jdbc.properties");//1、插入操作的sql语句。含有三个占位符,也就是三个问号。sql = "INSERT INTO customers(ste_id, name, email) VALUES(?, ?, ?)";JDBCDAO.update(connection, sql, 7, "李雷", "lilei@126.com");//2、执行删除操作sql = "DELETE FROM customers WHERE ste_id = ?";JDBCDAO.update(connection, sql, 5);//3、执行更新操作sql = "UPDATE customers SET email = ? WHERE ste_id = ?";JDBCDAO.update(connection, sql, "123456789@110.com",5);}}
再看查询操作,查询操作涉及到返回结果。所以较为复杂。
首先介绍查询的返回结果ResultSet:它的结构和数据库查询是一样的。如果返回一条记录,则只有一行;如果查询返回多行记录,则就有多行。而列数则和查询语句是一致的。如下:
如果执行resultSet.next()一次,则游标向下移动一行,指向"露西"。如果再执行一次,游标又向下移动一行。而列数,我的select语句中只查询了id, name, email,那么结果中就只有三列。
下面看看返回一行的函数:
<pre name="code" class="java"><pre name="code" class="java">
/** * 查询,并返回一条记录。具有通用性,能够将表的结果和一个类的属性对应起来。 * 从而,可以将数据库的查询结果和类的方法结合起来,使得数据具有了具体的意义。 * 但是,该方法只会返回一条记录,即便sql查询返回的是多条记录也只返回第一条。 * @param clazz * @param connection * @param sql * @param objects * @return 查询结果的映射类的实例。 */public static <T> T get(Class<T> clazz, Connection connection, String sql, Object ...objects){PreparedStatement preStatement = null;ResultSet resultSet = null;ResultSetMetaData rsmd = null;//1、创建泛型类的对象,将作为结果返回。无论有没有都不要返回null,而应该返回空实例。T classObj = null;try {//2、利用反射创建类的实例classObj = clazz.newInstance();//3、得到preStatement实例preStatement = connection.prepareStatement(sql);//4、填充sql占位符for(int i = 0; i < objects.length; i++){preStatement.setObject(i + 1, objects[i]);}//5、执行sql语句,其返回结果为resulSetresultSet = preStatement.executeQuery();//6、处理返回结果,将其映射为一个类的实例。这样,数据库中查询出来的数据就具有了具体的含义。if(resultSet.next()){//如果有数据,则进行下面的处理,否则直接返回了String key = null; Object value = null;//7、ResultSetMetaData很好,能够知道ResultSet的列名,列的数目等等。rsmd = resultSet.getMetaData();//8、得到列数int columnCount = rsmd.getColumnCount();//9、将返回结果的每一列和类的一个属性对应,将其赋值给类的属性for(int i = 0; i < columnCount; i++){//获取列名key = rsmd.getColumnLabel(i + 1);//利用列名来查询对应的结果value = resultSet.getObject(key);//10、使用BeanUtils工具,处理getter和setter是很好的。有特定要求BeanUtils.setProperty(classObj, key, value);}}} catch (Exception e) {e.printStackTrace();}finally{//11、关闭资源JDBCTools.releseJDBC(resultSet, null, null, preStatement);}return classObj;}
看看具体的使用方法:
<pre name="code" class="java"><pre name="code" class="java">
package com.lj95801.cla1;import java.sql.Connection;import org.junit.Test;import com.lj95801.utils.JDBCDAO;import com.lj95801.utils.JDBCTools;public class TestJDBCDAO {@Testpublic void testGet() throws Exception{String sql = null;Connection connection = JDBCTools.getConnection("jdbc.properties");//就是通过别名将类的属性和查询数据的各个列联系起来的。别名是有特殊要求的。sql = "SELECT ste_id \"id\",name \"name\",email \"email\" " + "FROM customers WHERE ste_id = ?";Student student = JDBCDAO.get(Student.class, connection, sql, 13);System.out.println(student);}}
执行结果:
如果查询结果返回多个行呢?处理方法是:建立一个list,将每一行映射为一个类的实例,同时将这些类的实例都放到list中。当然,你完全可以将其放到map中。
<pre name="code" class="java"><pre name="code" class="java">
/** * 查询一组结果。比如说id>7的所有记录。将其保存为对应类型的list * @param clazz * @param connection * @param sql * @param objects * @return */public static <T> List<T> getForList(Class<T> clazz, Connection connection,String sql, Object... objects) {PreparedStatement preStatement = null;ResultSet resultSet = null;ResultSetMetaData rsmd = null;// 1、建立一个空的list,即便查询结果为空,我们也返回一个空的list,而返回null。好处很多。List<T> list = new ArrayList<T>();try {preStatement = connection.prepareStatement(sql);for (int i = 0; i < objects.length; i++) {preStatement.setObject(i + 1, objects[i]);}// 2、执行查询,结果存放在resultSet中resultSet = preStatement.executeQuery();// 3、遍历结果集if (resultSet.next()) {// 4、得到元数据rsmd = resultSet.getMetaData();// 5、获取列数int columnCount = rsmd.getColumnCount();do {//6、必须每一次遍历都要新建一个实例。因为list.add方法不是复制内容,而是添加引用地址。T classObj = clazz.newInstance();for (int i = 0; i < columnCount; i++) {String columnName = rsmd.getColumnLabel(i + 1);Object columnValue = resultSet.getObject(columnName);//7、完成数据到类的映射关系BeanUtils.setProperty(classObj, columnName, columnValue);}/* * 注意,这个list.add()这个方法不是将classObj的内容拷贝一份,而是将classObj的 * 地址添加到list中。从而,如果add以后,我再将classObj的内容改变了,那么list中对应 * 的内容也改变了。 */list.add(classObj);// 如果在下面修改classObj中id的内容,那么,list中对应的内容也将改变。// BeanUtils.setProperty(classObj, "id", 123456789);} while (resultSet.next());}} catch (Exception e) {e.printStackTrace();} finally {JDBCTools.releseJDBC(resultSet, null, null, preStatement);}return list;}
执行结果:
如果查询结果是一个值呢?比如说查询ste_id=9对应的name值,或者是email的值。看下面代码:
<pre name="code" class="java"><pre name="code" class="java">
/** * 查询结果返回一个值的时候,使用这个函数。 * @param connection * @param sql * @param objects * @return */public static <E> E getForValue(Connection connection, String sql, Object... objects) {PreparedStatement prepStatement = null;ResultSet resultSet = null;//1、用反射创建泛型类的实例E returnValue = null; //有待完善,这条语句没有完成泛型类引用的创建try {prepStatement = connection.prepareStatement(sql);for (int i = 0; i < objects.length; i++) {prepStatement.setObject(i + 1, objects[i]);}resultSet = prepStatement.executeQuery();//2、如果查询有返回结果if (resultSet.next()) {//3、将第一个结果赋值给E的引用,即便查询返回结果有多条,也值处理第一个。returnValue = (E) resultSet.getObject(1);}} catch (Exception e) {e.printStackTrace();}finally{JDBCTools.releseJDBC(resultSet, null, null, prepStatement);}return returnValue;}
现在为止,我们可以将代码综合一下,做一个JDBC工具类,代码如下:
package com.lj95801.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.beanutils.BeanUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class JDBCUtils {
/*使用C3P0来创建和管理数据库连接池*/
private static ComboPooledDataSource cpds = null;
/**
* 利用C3P0获取数据库连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
if(cpds == null){
cpds = new ComboPooledDataSource("HelloC3P0");
}
return cpds.getConnection();
}
/**
* 编写一个通用的方法, 在不修改源程序的情况下, 可以获取任何数据库的连接
* 解决方案: 把数据库驱动 Driver 实现类的全类名、url、user、password 放入一个
* 配置文件中, 通过修改配置文件的方式实现和具体的数据库解耦.
* @param propertiesFile: 数据库的配置文件
* @return connection 数据库链接
*/
public Connection getConnection(String propertiesFile){
//1、读取类路径下的 jdbc.properties 文件,获得具体driver实现类和三样东西。
InputStream in = null;
//3、通过 Driver 的 connect 方法获取数据库连接.
Connection connection = null;
try {
String driverClass = null;
String jdbcUrl = null;
String user = null;
String password = null;
in = this.getClass().getClassLoader().getResourceAsStream(propertiesFile);
Properties properties = new Properties();
properties.load(in);
driverClass = properties.getProperty("driver");
jdbcUrl = properties.getProperty("jdbcUrl");
user = properties.getProperty("user");
password = properties.getProperty("password");
//2、通过反射创建Driver 对象.
Driver driver =
(Driver) Class.forName(driverClass).newInstance();
Properties info = new Properties();
info.put("user", user);
info.put("password", password);
//3、得到数据库链接
connection = driver.connect(jdbcUrl, info);
} catch (IOException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return connection;
}
/**
* 更新。可处理的操作有:更新,删除,插入三种操作。
*
* @param connection
* @param sql
* @param objects
*/
public static void update(Connection connection, String sql,
Object... objects) {
PreparedStatement preStatement = null;
try {
// 1、通过connection得到preStatement,它可以为sql占位符填充内容,防止sql注入
preStatement = connection.prepareStatement(sql);
// 2、for循环为sql语句填充占位符
for (int i = 0; i < objects.length; i++) {
preStatement.setObject(i + 1, objects[i]);
}
// 3、调用executeUpdate()方法执行更新
preStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 4、释放资源
release(null, preStatement, null, null);
}
}
/**
* 查询,并返回一条记录。具有通用性,能够将表的结果和一个类的属性对应起来。
* 从而,可以将数据库的查询结果和类的方法结合起来,使得数据具有了具体的意义。
* 但是,该方法只会返回一条记录,即便sql查询返回的是多条记录也只返回第一条。
*
* @param clazz
* @param connection
* @param sql
* @param objects
* @return 查询结果的映射类的实例。
*/
public static <T> T get(Class<T> clazz, Connection connection, String sql,
Object... objects) {
PreparedStatement preStatement = null;
ResultSet resultSet = null;
ResultSetMetaData rsmd = null;
// 1、创建泛型类的对象,将作为结果返回。无论有没有都不要返回null,而应该返回空实例。
T classObj = null;
try {
// 2、利用反射创建类的实例
classObj = clazz.newInstance();
// 3、得到preStatement实例
preStatement = connection.prepareStatement(sql);
// 4、填充sql占位符
for (int i = 0; i < objects.length; i++) {
preStatement.setObject(i + 1, objects[i]);
}
// 5、执行sql语句,其返回结果为resulSet
resultSet = preStatement.executeQuery();
// 6、处理返回结果,将其映射为一个类的实例。这样,数据库中查询出来的数据就具有了具体的含义。
if (resultSet.next()) {// 如果有数据,则进行下面的处理,否则直接返回了
String key = null;
Object value = null;
// 7、ResultSetMetaData很好,能够知道ResultSet的列名,列的数目等等。
rsmd = resultSet.getMetaData();
// 8、得到列数
int columnCount = rsmd.getColumnCount();
// 9、将返回结果的每一列和类的一个属性对应,将其赋值给类的属性
for (int i = 0; i < columnCount; i++) {
// 获取列名
key = rsmd.getColumnLabel(i + 1);
// 利用列名来查询对应的结果
value = resultSet.getObject(key);
// 10、使用BeanUtils工具,处理getter和setter是很好的。有特定要求
BeanUtils.setProperty(classObj, key, value);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 11、关闭资源
release(resultSet, preStatement, null, null);
}
return classObj;
}
/**
* 查询一组结果。比如说id>7的所有记录。将其保存为对应类型的list
* @param clazz
* @param connection
* @param sql
* @param objects
* @return
*/
public static <T> List<T> getForList(Class<T> clazz, Connection connection,
String sql, Object... objects) {
PreparedStatement preStatement = null;
ResultSet resultSet = null;
ResultSetMetaData rsmd = null;
// 1、建立一个空的list,即便查询结果为空,我们也返回一个空的list,而返回null。好处很多。
List<T> list = new ArrayList<T>();
try {
preStatement = connection.prepareStatement(sql);
for (int i = 0; i < objects.length; i++) {
preStatement.setObject(i + 1, objects[i]);
}
// 2、执行查询,结果存放在resultSet中
resultSet = preStatement.executeQuery();
// 3、遍历结果集
if (resultSet.next()) {
// 4、得到元数据
rsmd = resultSet.getMetaData();
// 5、获取列数
int columnCount = rsmd.getColumnCount();
do {
//6、必须每一次遍历都要新建一个实例。因为list.add方法不是复制内容,而是添加引用地址。
T classObj = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
String columnName = rsmd.getColumnLabel(i + 1);
Object columnValue = resultSet.getObject(columnName);
//7、完成数据到类的映射关系
BeanUtils.setProperty(classObj, columnName, columnValue);
}
/*
* 注意,这个list.add()这个方法不是将classObj的内容拷贝一份,而是将classObj的
* 地址添加到list中。从而,如果add以后,我再将classObj的内容改变了,那么list中对应
* 的内容也改变了。
*/
list.add(classObj);
// 如果在下面修改classObj中id的内容,那么,list中对应的内容也将改变。
// BeanUtils.setProperty(classObj, "id", 123456789);
} while (resultSet.next());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
release(resultSet, preStatement, null, null);
}
return list;
}
/**
* 查询结果返回一个值的时候,使用这个函数。
* @param connection
* @param sql
* @param objects
* @return
*/
public static <E> E getForValue(Connection connection, String sql, Object... objects) {
PreparedStatement prepStatement = null;
ResultSet resultSet = null;
//1、用反射创建泛型类的实例
E returnValue = null; //有待完善,这条语句没有完成泛型类引用的创建
try {
prepStatement = connection.prepareStatement(sql);
for (int i = 0; i < objects.length; i++) {
prepStatement.setObject(i + 1, objects[i]);
}
resultSet = prepStatement.executeQuery();
//2、如果查询有返回结果
if (resultSet.next()) {
//3、将第一个结果赋值给E的引用,即便查询返回结果有多条,也值处理第一个。
returnValue = (E) resultSet.getObject(1);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
release(resultSet, prepStatement, null, null);
}
return returnValue;
}
/**
* 关闭资源。保证每个资源都能够完成关闭。
* @param resultSet
* @param preStatement
* @param statement
* @param connection
*/
public static void release(ResultSet resultSet, PreparedStatement preStatement,
Statement statement, Connection connection){
try {
try {
if(resultSet != null){
resultSet.close();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(preStatement != null){
preStatement.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(statement != null){
statement.close();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
C3P0配置文件如下(文件名为:c3p0-config.xml):
<c3p0-config>
<!-- This app is massive! -->
<named-config name="HelloC3P0">
<!-- 指定连接数据源的基本属性 -->
<property name="user">scott</property>
<property name="password">tiger</property>
<property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
<property name="jdbcUrl">jdbc:oracle:thin:@localhost:1521:orcl</property>
<!-- 若数据库连接池不足时,一次向数据库申请多少个连接 -->
<property name="acquireIncrement">5</property>
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize">5</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">1000</property>
<!-- C3P0数据库连接池可以维护的Statement的个数 -->
<property name="maxStatements">0</property>
<!-- 每个连接同时可以使用的Statement个数 -->
<property name="maxStatementsPerConnection">5</property>
</named-config>
</c3p0-config>