利用JDBC操作数据库的常用方法,首先加载数据库的驱动(Driver),获取数据库的连接对象(Connection),然后由连接对象创建操作数据库的语句对象(Statement),利用语句对象对数据库执行操作,得到结果集对象(ResultSet)获取结果数据内容。示例程序代码如下:
Class.forName(jdbcDriver);
Connection connection = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
Statement stmt = connection.createStatement();
ResultSet resultSet = stmt.executeQuery(queryState);
while (resultSet.next()){
System.out.println(resultSet.getRow() + "--" + resultSet.getInt(1) +"--" + resultSet.getString(2) );
}
每次对数据库进行操作时,重新获取数据库连接时,时间消耗等比较大,可以建立一个连接池保存一定数量的连接,当有对象需要数据库连接时,直接将这个连接返回给该对象,不再用重新获取数据库连接,加载驱动等;在初始化连接池对象时加载一次驱动,后面都不再需要加载驱动,利用一个List将数据库连接保存起来,当有对象需要连接时,直接在List中返回一个空闲的连接给该对象,该对象用完后将该连接返回到数据库连接池,方便下次继续使用;
PooledConnection类将Connection对象包装了一下,用于判断该连接是否空闲,如果空闲就返回该连接。
public class PooledConnection {
Connection connection = null; ///数据库连接
boolean busy = false; ///该连接是否正使用
根据一个Connection构造一个PooledConnection
public PooledConnection(Connection connection) {
this.connection = connection;
}
/**
* 获取该连接对象
**/
public Connection getConnection() {
return connection;
}
/**
* 设置该连接
*/
public void setConnection(Connection connection) {
this.connection = connection;
}
/**
* 该连接是否空闲
**/
public boolean isBusy() {
return busy;
}
/**
* 设置该连接是否空闲
**/
public void setBusy(boolean busy) {
this.busy = busy;
}
}
ConnectionPool连接池的具体实现:
class ConnectionPool {
private String jdbcDriver = ""; // 数据库驱动
private String dbUrl = ""; // 数据 URL
private String dbUsername = ""; // 数据库用户名
private String dbPassword = ""; // 数据库用户密码
private String testTable = ""; // 测试连接是否可用的测试表名,默认没有测试表
private int initialConnections = 10; // 连接池的初始大小
private int incrementalConnections = 5;// 连接池自动增加的大小
private int maxConnections = 800; // 连接池最大的大小
private List<PooledConnection> connections = null; // 存放连接池中数据库连接的列表 , 初始时为 null
public ConnectionPool(String jdbcDriver, String dbUrl, String dbUsername, String dbPassword) {
this.jdbcDriver = jdbcDriver;
this.dbUrl = dbUrl;
this.dbUsername = dbUsername;
this.dbPassword = dbPassword;
try {
createPool();//初始化时创建连接池
} catch (Exception e) {
e.printStackTrace();
}
}
void setIncrementalConnections(int incrementalConnections) {
this.incrementalConnections = incrementalConnections;
}
void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
/**
* 创建数据库连接池,连接池初始数量由initialConnections确定
**/
private synchronized void createPool() throws ClassNotFoundException, SQLException, IllegalAccessException, InstantiationException {
if(connections != null){
return; ///如果已经创建了连接池,返回这个连接池
}
// Driver driver = (Driver)(Class.forName(this.jdbcDriver).newInstance());
// DriverManager.registerDriver(driver); ///注册驱动
Class.forName(this.jdbcDriver); 只是在创建连接池时加载一次驱动
connections = new ArrayList();
根据initialConnections创建连接数目
createConnection(this.initialConnections);
}
/**
* @param initialConnections 要创建的数据库连接数目
**/
private void createConnection(int initialConnections) throws SQLException {
根据initialConnections创建连接
for (int x = 0; x < initialConnections; x++){
///如果连接数目已经达到最大,退出不创建连接
if(this.maxConnections > 0 && this.connections.size() > this.maxConnections){
break;
}///end if
try {
///将Connection对象用PooledConnection包装放入List当中
connections.add(new PooledConnection(newConnection()));
} catch (SQLException e) {
System.out.println("创建数据库连接失败!");
throw new SQLException();
}
}
}
/**
* 创建一个新的连接,并且返回这个连接
**/
private Connection newConnection() throws SQLException {
///创建一个数据库连接
Connection connection = DriverManager.getConnection(dbUrl, dbUsername,dbPassword);
///如果是第一次创建数据连接,检查数据库,获取数据库最大连接数目
if(connections.size() == 0){
DatabaseMetaData metaData = connection.getMetaData();
int driverMaxConnections = metaData.getMaxConnections();
数据库返回0则说明无最大连接数目限制,将最大连接数据设置为数据库返回的数目
if(driverMaxConnections > 0 && this.maxConnections > driverMaxConnections){
this.maxConnections = driverMaxConnections;
}
}///end if
return connection; ///返回新创建的数据库连接
}
/**
* 同步获取当前可用的一个数据库连接对象
**/
synchronized Connection getConnection() throws SQLException {
///确保连接池已经被创建完成
if(connections == null){
return null;
}
Connection connection = getFreeConnection(); ///获取一个空闲的连接
如果当前没有可用的连接,等一会再试
while (connection == null){
wait(250);
connection = getFreeConnection();
}
return connection;
}
private Connection getFreeConnection() throws SQLException {
Connection connection = findFreeConnection();
if(connection == null){
如果当前连接池没有可用连接了,创建一些连接
createConnection(incrementalConnections);
///重新从池中查找空闭连接
connection = findFreeConnection();
if(connection == null)
return null;///如果还是找不到则返回空
}
return connection;
}
private Connection findFreeConnection() {
Connection connection = null;
PooledConnection pConn = null;
///获得连接池所有连接
Iterator iterator = connections.iterator();
///遍历所有连接,查找可用连接
while (iterator.hasNext()){
pConn = (PooledConnection)iterator.next();
///如果当前连接是空闲的
if(!pConn.isBusy()){
///当前连接不忙,获取它的连接设当前连接忙碌
connection = pConn.getConnection();
pConn.setBusy(true);
测试当前连接是否可用
if(!testConnection(connection)){
///如果不可用,创建一个新的连接并替换原来那个
try{
connection = newConnection();
} catch (SQLException e) {
System.out.println("创建数据库失败!" + e.getMessage());
return null;
}
pConn.setConnection(connection);
}
break;///已经找到一个可用连接
}
}
return connection;
}
/**
* 测试一个连接是否可用,如果不可用,关掉它并且返回false
* @param connection 需要测试的连接
**/
private boolean testConnection(Connection connection) {
try {
if(testTable.equals("")){
connection.setAutoCommit(true);
}else{
Statement stmt = connection.createStatement();
stmt.execute("select count(*) from " + testTable);
}
} catch (SQLException e) {
closeConnection(connection);
return false;
}
///连接可用
return true;
}
/**
* 将指定数据库连接对象返回到连接池,下次可以重用
*@param connection 要返回连接池的连接
*/
public void returnConnection(Connection connection){
///确保连接池存在
if(connections == null){
System.out.println("连接池不存在,无法返回连接!");
return;
}
PooledConnection pConn = null;
Iterator iterator =connections.iterator();
while (iterator.hasNext()){
pConn = (PooledConnection)iterator.next();
if(pConn.getConnection() == connection){
pConn.setBusy(false); ///将该连接设置为空闲状态
break;
}
}
}
/**
* 刷新当前连接池里面的所有连接
**/
public synchronized void refreshConnection() throws SQLException {
///确保连接池存在
if(connections == null){
System.out.println("连接池不存在,无法返回连接!");
return;
}
Iterator iterator = this.connections.iterator();
PooledConnection pConn = null;
while (iterator.hasNext()){
pConn = (PooledConnection)iterator.next();
if (pConn.isBusy()){
wait(5000);
}///当前连接不空闲,等待5秒
closeConnection(pConn.connection);
pConn.setConnection(newConnection());
pConn.setBusy(false);
}
}
/**
* 关闭连接池中所有的连接,并清空连接池。
*/
public synchronized void closeConnectionPool() throws SQLException {
// 确保连接池存在,如果不存在,返回
if (connections == null) {
System.out.println(" 连接池不存在,无法关闭 !");
return;
}
for (PooledConnection pConn : this.connections){
pConn = (PooledConnection)pConn;
if (pConn.isBusy()){
wait(5000);
}///当前连接不空闲,等待5秒
closeConnection(pConn.getConnection());
}
this.connections.clear();
this.connections = null;
}
/**
* 关闭一个数据库连接
*
* @param conn 需要关闭的数据库连接
*/
private void closeConnection(Connection conn) {
try {
conn.close();
} catch (SQLException e) {
System.out.println(" 关闭数据库连接出错: " + e.getMessage());
}
}
private void wait(int mills){
try {
Thread.sleep(mills);
} catch (InterruptedException e) {
System.out.println("等待线程中断了~");
e.printStackTrace();
}
}
}
ConnectionPoolFactory类组合了ConnectionPool连接池,包装ConnectionPool了提供获取数据库连接,关闭数据库连接池,刷新数据库连接池,返回连接到连接池方法。让ConnectionPool对象成为ConnectionPoolFactory类的类变量保证只有一个连接池(ConnectionPool),提供的连接都是从这个连接池中提供的。
public class ConnectionPoolFactory {
private static final ConnectionPool connectionPool;
///PropertiesUtil读取数据库配置文件
static {
PropertiesUtil.reloadPropes();
HashMap<String, String> propes = PropertiesUtil.getDbProps();
String jdbcDriver = propes.get(App.JDBC_DRIVER);
String dbUrl = propes.get(App.DB_URL);
String userName = propes.get(App.DB_USERNAME);
String password = propes.get(App.DB_PASSWORD);
System.out.println(jdbcDriver + "--" + dbUrl);
connectionPool = new ConnectionPool(jdbcDriver, dbUrl, userName, password);
}
public static Connection getConnection() throws SQLException {
return connectionPool.getConnection();
}
public static void returnConnection(Connection connection){
connectionPool.returnConnection(connection);
}
public static void refreshConnection() throws SQLException {
connectionPool.refreshConnection();
}
public static void closeConnectionPool() throws SQLException {
connectionPool.closeConnectionPool();;
}
public static void setMaxConnections(int maxConnections) {
connectionPool.setMaxConnections(maxConnections);
}
public void setIncrementalConnections(int incrementalConnections) {
connectionPool.setIncrementalConnections(incrementalConnections);
}
static ConnectionPool getConnectionPool() {
return connectionPool;
}
}