在使用JDBC时我们可以自己去创建一个工具类(JDBCUtils),每次来调用它的方法来获取连接或者来释放连接,具体该类的实现如下:
package JDBCUtils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ResourceBundle;
//获取连接和释放资源的方法
public class JDBCUtils {
private static String driver;
private static String url;
private static String username;
private static String password;
//静态代码块
static {
//读取配置文件
ResourceBundle bundle=ResourceBundle.getBundle("db");
//获取文件中的数据
driver=bundle.getString("driver");
url=bundle.getString("url");
username=bundle.getString("username");
password=bundle.getString("password");
}
//获取连接
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName(driver);
conn=DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
//释放资源
public static void release(Connection conn,PreparedStatement pstmt,ResultSet rs){
if(rs!=null)
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(pstmt!=null)
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(conn!=null)
try {
rs.close();
} catch (SQLException e){
e.printStackTrace();
}
}
}
在这里我们使用配置文件来存储链接数据库所需要的信息,配置文件名为db.properties
这个类中有两个方法,一是来获取数据库的连接,二是来释放资源
但是,如果反复的创建资源释放资源,这会造成很大的浪费,所以,我们可以使用jdbc连接池来存放,在连接池中我们可以存放多个已经事先创建好的连接,每次使用时只需要取出来,使用完后再放回去,这样做提高了效率。
package DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.logging.Logger;
import javax.sql.DataSource;
import JDBCUtils.JDBCUtils;
public class MyDataSource implements DataSource{
//创建集合用来存储conn
private static ArrayList pool=new ArrayList<>();
//使用静态代码块创建5个连接放到连接池中
static {
Connection conn=null;
for(int i=0;i<5;i++) {
conn=JDBCUtils.getConnection();
pool.add(conn);
}
}
//写返回类
@Override
public Connection getConnection() throws SQLException {
Connection conn=null;
//判断是否为空
if(pool==null) {
for(int i=0;i<5;i++) {
conn=JDBCUtils.getConnection();
pool.add(conn);
}
}
//删除第一个
conn=pool.remove(0);
return conn;
}
//写回收方法
public void backConnection(Connection conn){
pool.add(conn);
}
//!!!!.....此处省略了很多需要写上的类
}
创建连接池的大概思路就是,我们先创建一个集合(池),然后通过静态代码块创建多个(上段代码创建了5个)连接,然后将他们全部放到集合中,如果每次要获得连接,直接从集合中取出一个,使用完后再调用这个类中的返回方法将连接归还
这是测试类:
public class TestMyDataSource {
@Test
public void Test() {
Connection conn=null;
PreparedStatement pstmt=null;
MyDataSource datasource=new MyDataSource();
try {
//获取连接
conn=datasource.getConnection();
String sql="insert into t_user values(null,?,?)";
pstmt=conn.prepareStatement(sql);
pstmt.setString(1,"aaa");
pstmt.setString(2,"666");
int x=pstmt.executeUpdate();
if(x>0) {
System.out.println("操作成功");
}else {
System.out.println("操作失败");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
datasource.backConnection(conn);
}
}
}
通过测试,成功的将数据填入数据库中。
这是一种使用连接池的方法,如果我们要在最后依然习惯性的调用JDBCUtils中的方法release方法,但是这样就会释放连接,我们想让他中的close方法不是释放而是归还,那么我们就需要重写这个方法,首先创建一个Connection类
package 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.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
public class MyConnection implements Connection{
private Connection conn;
private ArrayList pool;
public MyConnection(Connection conn,ArrayList pool){
this.conn=conn;
this.pool=pool;
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return conn.prepareStatement(sql);
}
@Override
public void close() throws SQLException {
pool.add(conn);
}
//!!!、、、、、此处省略了许多必须存在的方法
}
这里我们床架一个类,实际这个类就是对conn连接的一个封装,我们再写一个创建连接池的类,和上一个差不多
package DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.logging.Logger;
import javax.sql.DataSource;
import JDBCUtils.JDBCUtils;
public class MyDataSource1 implements DataSource{
//创建集合用来存储conn
private static ArrayList pool=new ArrayList<>();
//使用静态代码块创建5个连接放到连接池中
static {
Connection conn=null;
for(int i=0;i<5;i++) {
conn=JDBCUtils.getConnection();
MyConnection myconn=new MyConnection(conn, pool);
pool.add(myconn);
}
}
//写返回类
@Override
public Connection getConnection() throws SQLException {
Connection conn=null;
//判断是否为空
if(pool==null) {
for(int i=0;i<5;i++) {
conn=JDBCUtils.getConnection();
MyConnection myconn=new MyConnection(conn, pool);
pool.add(myconn);
}
}
//删除第一个
conn=pool.remove(0);
return conn;
}
//此处省略多个必须存在方法
}
实际我们可以看到我们现在通过这个方法所得到的conn连接实际不是Connection了解,而是他的子类MyConnection,是一个封装对象,我们再得到它后,就对它进行使用
@Test
public void Test1() {
Connection myconn=null;
PreparedStatement pstmt=null;
MyDataSource1 datasource1=new MyDataSource1();
try {
//获取连接
myconn=datasource1.getConnection();
String sql="insert into t_user values(null,?,?)";
pstmt=myconn.prepareStatement(sql);
pstmt.setString(1,"wae1");
pstmt.setString(2,"6661");
int x=pstmt.executeUpdate();
if(x>0) {
System.out.println("操作成功");
}else {
System.out.println("操作失败");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.release(myconn, pstmt, null);
}
}
通过测试,成功的添加了信息到数据库中,起始在全部过程中,我们所操作的只是Connection的封装类,并没有操作实际的Connec,最后调用JDBCUtils中的release方法,它中有close方法,再调用MyConnection中的close将连接放回连接池中。