Java操作数据库——使用连接池连接数据库

Java操作数据库——使用连接池连接数据库

摘要:本文主要学习了如何使用JDBC连接池连接数据库。

传统方式和连接池方式

传统方式的步骤

使用传统方式在Java中使用JDBC连接数据库,完成一次数据库的操作,一般有以下几个步骤:

加载驱动。

建立连接。

执行SQL语句。

释放连接。

传统方式的弊端

每一次对数据库的操作都要建立一次连接,并且会将得到的Connection对象加载到内存中,导致消耗了大量的内存和时间。如果短时间有很多需要进行建立连接的操作,会导致占用很多系统资源,甚至会导致服务器崩溃。

同建立连接相对应,每次使用都需要手动释放连接,如果忘记释放连接或者程序出现异常未能成功释放,会导致内存泄露。

此外,传统方式并不能控制连接的数量,如果连接的人数过多,会导致无限制的创建连接对象,导致内存开销过大,服务器崩溃。

连接池的步骤

创建连接池并配置连接属性。

使用连接池获取连接。

连接池的优势

每次需要连接数据库时,不需要建立连接,而是通过连接池获取,由连接池提供连接。

在使用完连接后,不需要手动释放连接,而是交由连接池释放连接。

可以通过连接池控制连接的数量,在连接池里的连接可多次重复使用,避免了无限制创建连接的问题。

使用连接池

使用C3P0连接池

C3P0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。

导入jar包:

1 c3p0-0.9.5.2.jar

在当前项目的代码根目录 src 下新建名为 c3p0-config.xml 的配置文件,注意文件名称不可改变,内容如下:

 1 <c3p0-config>
 2     <!-- 连接名称 -->
 3     <named-config name="mysql">
 4         <!-- 接数据库的驱动类名 -->
 5         <property name="driverClass">com.mysql.jdbc.Driver</property>
 6         <!-- 连接属性 -->
 7         <property name="jdbcUrl">jdbc:mysql://192.168.35.128:3306/demo</property>
 8         <property name="user">root</property>
 9         <property name="password">123456</property>
10         <!-- 当连接池用完时等待获取新连接的时间,超时后将抛出SQLException,单位毫秒,如设为0则无限期等待。默认为0。 -->
11         <property name="checkoutTimeout">5000</property>
12         <!-- 当连接用尽后,一次获取的连接个数 -->
13         <property name="acquireIncrement">2</property>
14         <!-- 初始连接数 -->
15         <property name="initialPoolSize">1</property>
16         <!-- 最小连接数 -->
17         <property name="minPoolSize">3</property>
18         <!-- 最大连接数 -->
19         <property name="maxPoolSize">5</property>
20     </named-config>
21 </c3p0-config>

程序代码:

 1 public class TestDataPool {
 2     // 根据配置文件里的名称创建连接池
 3     public static ComboPooledDataSource cpds = new ComboPooledDataSource("mysql");
 4     
 5     /**
 6      * 主程序
 7      */
 8     public static void main(String[] args) {
 9         // 模拟多次对数据库的查询操作
10         for (int i = 0; i < 6; i++) {
11             new Thread(new Runnable() {
12                 @Override
13                 public void run() {
14                     select();
15                 }
16             }, "线程" + i).start();
17         }
18     }
19     
20     /**
21      * 查询程序
22      */
23     public static void select() {
24         Connection conn = null;
25         PreparedStatement pstmt = null;
26         ResultSet rs = null;
27         // 获取连接并执行SQL
28         try {
29             conn = cpds.getConnection();
30             pstmt = conn.prepareStatement("select * from student where id = 906");
31             rs = pstmt.executeQuery();
32             while (rs.next()) {
33                 System.out.println(Thread.currentThread().getName() + "	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString("address"));
34             }
35         } catch (Exception e) {
36             e.printStackTrace();
37         } finally {
38             // 释放资源
39             try {
40                 rs.close();
41             } catch (SQLException e) {
42                 e.printStackTrace();
43             }
44             try {
45                 pstmt.close();
46             } catch (SQLException e) {
47                 e.printStackTrace();
48             }
49             try {
50                 conn.close();
51             } catch (SQLException e) {
52                 e.printStackTrace();
53             }
54         }
55     }
56 }

使用DBCP连接池

DBCP是Apache上的一个Java连接池项目,是一个依赖Jakarta项目commons-pool对象池机制的数据库连接池。DBCP可以直接的在应用程序中使用,Tomcat的数据源使用的就是DBCP。

导入jar包:

1 commons-dbcp-1.4.jar2 commons-pool-1.5.5.jar

在当前项目的代码根目录 src 下新建名为 dbcp.properties 的配置文件,文件名需要同代码中引用的文件名一致,内容如下:

 1 # 接数据库的驱动类名
 2 driverClassName=com.mysql.jdbc.Driver
 3 # 连接属性
 4 url=jdbc:mysql://192.168.35.128:3306/demo
 5 username=root
 6 password=123456
 7 # 初始化连接数
 8 initialSize=10
 9 # 最大连接数
10 maxActive=15

程序代码:

 1 public class TestDBCP {
 2     // 根据配置文件里的名称创建连接池
 3     private static DataSource source = null;
 4     static {
 5         Properties pros = new Properties();
 6         InputStream is = TestDBCP.class.getClassLoader().getResourceAsStream("dbcp.properties");
 7         try {
 8             pros.load(is);
 9             source = BasicDataSourceFactory.createDataSource(pros);
10         } catch (Exception e) {
11             e.printStackTrace();
12         }
13     }
14 
15     /**
16      * 主程序
17      */
18     public static void main(String[] args) {
19         // 模拟多次对数据库的查询操作
20         for (int i = 0; i < 6; i++) {
21             new Thread(new Runnable() {
22                 @Override
23                 public void run() {
24                     select();
25                 }
26             }, "线程" + i).start();
27         }
28     }
29 
30     /**
31      * 查询程序
32      */
33     public static void select() {
34         Connection conn = null;
35         PreparedStatement pstmt = null;
36         ResultSet rs = null;
37         // 获取连接并执行SQL
38         try {
39             conn = source.getConnection();
40             pstmt = conn.prepareStatement("select * from student where id = 906");
41             rs = pstmt.executeQuery();
42             while (rs.next()) {
43                 System.out.println(Thread.currentThread().getName() + "	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString("address"));
44             }
45         } catch (Exception e) {
46             e.printStackTrace();
47         } finally {
48             // 释放资源
49             try {
50                 rs.close();
51             } catch (SQLException e) {
52                 e.printStackTrace();
53             }
54             try {
55                 pstmt.close();
56             } catch (SQLException e) {
57                 e.printStackTrace();
58             }
59             try {
60                 conn.close();
61             } catch (SQLException e) {
62                 e.printStackTrace();
63             }
64         }
65     }
66 }

使用Druid连接池

Druid是阿里巴巴出品的数据源,而且是淘宝和支付宝专用数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser。

导入jar包:

1 druid-1.0.9.jar

在当前项目的代码根目录 src 下新建名为 druid.properties 的配置文件,文件名需要同代码中引用的文件名一致,内容如下:

 1 # 接数据库的驱动类名
 2 driverClassName=com.mysql.jdbc.Driver
 3 # 连接属性
 4 url=jdbc:mysql://192.168.35.128:3306/demo
 5 username=root
 6 password=123456
 7 # 最大连接数
 8 maxActive=15
 9 # 最长等待时间
10 maxWait=3000
11 # 配置初始化连接数
12 initialSize=1
13 # 配置最大活动连接数
14 maxActive=10

程序代码:

 1 public class TestDruid {
 2     // 根据配置文件里的名称创建连接池
 3     private static DataSource source = null;
 4     static {
 5         Properties pros = new Properties();
 6         InputStream is = TestDruid.class.getClassLoader().getResourceAsStream("druid.properties");
 7         try {
 8             pros.load(is);
 9             source = DruidDataSourceFactory.createDataSource(pros);
10         } catch (Exception e) {
11             e.printStackTrace();
12         }
13     }
14 
15     /**
16      * 主程序
17      */
18     public static void main(String[] args) {
19         // 模拟多次对数据库的查询操作
20         for (int i = 0; i < 6; i++) {
21             new Thread(new Runnable() {
22                 @Override
23                 public void run() {
24                     select();
25                 }
26             }, "线程" + i).start();
27         }
28     }
29 
30     /**
31      * 查询程序
32      */
33     public static void select() {
34         Connection conn = null;
35         PreparedStatement pstmt = null;
36         ResultSet rs = null;
37         // 获取连接并执行SQL
38         try {
39             conn = source.getConnection();
40             pstmt = conn.prepareStatement("select * from student where id = 906");
41             rs = pstmt.executeQuery();
42             while (rs.next()) {
43                 System.out.println(Thread.currentThread().getName() + "	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString("address"));
44             }
45         } catch (Exception e) {
46             e.printStackTrace();
47         } finally {
48             // 释放资源
49             try {
50                 rs.close();
51             } catch (SQLException e) {
52                 e.printStackTrace();
53             }
54             try {
55                 pstmt.close();
56             } catch (SQLException e) {
57                 e.printStackTrace();
58             }
59             try {
60                 conn.close();
61             } catch (SQLException e) {
62                 e.printStackTrace();
63             }
64         }
65     }
66 }
原文地址:https://www.cnblogs.com/shamao/p/11928905.html