自定义一个简单的JDBC连接池

一、什么是JDBC连接池

在传统的JDBC连接中,每次获得一个Connection连接都需要加载通过一些繁杂的代码去获取,例如以下代码:

public static Connection getConn(){ Connection conn = null; String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "root"; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection(url, user, password); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return conn; }

这样繁杂的操作只为了获取一次连接,当然,我们可以将其封装成一个工具类来访问(上图以封装好Connection的连接),但是每一次连接都需要取加载一次是不是很浪费性能,为了优化性能,那么就出现了连接池。

连接池在初始化的时候就创建了几个连接供我们使用,当我们需要连接时只需要从连接池中获取已存在的连接,当初始化的几个连接都没有时,会重新创建一个连接,使用完连接后不会去销毁连接,而是归还给连接池供后面需要连接的使用。(当然,连接池不仅仅只是这么简单,这里就只做这些介绍)

常用的连接池有DBCP、C3P0,现在最主流是好像是阿里的Druid连接池,还有tomcat的自带的JNDI连接池

二、自定义一个简单的连接池

对自定义连接池的分析:

1.2.因为是连接池 ,我们需要实现DataSource接口,并实现其中的方法,基于我们的情况,我们关于与getConnection()方法;

2.既然要存放几个连接对象,那么我们用一个集合来存放它,基于会经常操作增加和删除那么选用LinkedList;

3.连接的销毁并不是销毁连接,而是将连接归还给连接池

编码:

1.创建一个类MyDataSource 并实现DataSource接口

当此类加载时它就需要有一个容器来存放Connection,所以定义一个静态的属性:

private static List<Connection> connectionList = new LinkedList<>();

2.因为需要取获得数据库连接,所以我们封装一个获取数据库连接的方法

public Connection getOneConnection(){ Connection conn = null; try{
//此处通过外部的properties文件来获取的数据,这样更加灵活。 InputStream in
= MyDataSource.class.getClassLoader(). getResourceAsStream("jdbc/jdbc.properties"); Properties pro = new Properties(); pro.load(in); driver = pro.getProperty("driver"); url = pro.getProperty("url"); username = pro.getProperty("user"); password = pro.getProperty("password"); Class.forName(driver); conn = DriverManager.getConnection(url,username,password); }catch (Exception e){ e.getStackTrace(); } return conn; }

注意的是我这里通过propertie文件的获取的数据,可根据实际情况来选择

3.初始化几个连接放入容器中。可以使用静态代码块来实现,但是如果没有使用此数据源那么就造成了资源的浪费,所以我考虑将初始化几个连接的实现放到他的构造方法中,即当需要此连接池的时候他才会随之创建几个连接。如下:

public MyDataSource() { for (int i = 0; i < 5; i++) { Connection conn = getOneConnection();//调用创建连接的方法 connectionList.add(conn); } }

4.现在开始重写外部从此连接池中获取连接的方法getConnection()

@Override public Connection getConnection() throws SQLException { Connection conn = null; if(connectionList == null || connectionList.size() <= 0){ Connection connection = getConnection(); connectionList.add(connection); } conn = connectionList.remove(0); return conn; }

5.创建一个对象返回的方法,即将用完的连接放入归还到连接池中

public void backConnection(Connection conn){ connectionList.add(conn); }

OK,这样就完成了一个简单的自定义连接池,测试代码如下:

public static void main( String[] args ) throws SQLException { MyDataSource dataSource = new MyDataSource(); Connection conn = dataSource.getConnection(); String sql = "select * from user where u_id = ?"; PreparedStatement ps = null; ResultSet rs = null; try { ps = conn.prepareStatement(sql); ps.setInt(1, 1); rs = ps.executeQuery(); while (rs.next()) { System.out.println("id="+rs.getInt(1)); System.out.println("username="+rs.getString(2)); System.out.println("password="+rs.getString(3)); } } catch (SQLException e) { e.printStackTrace(); } finally { dataSource.backConnection(conn); } }

因为忽略,我的代码中没有关闭其他两个对象。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/386c28c5800423bc4afc314e89e553b1.html