在这之前,我们使用的都是JDBCUtil工具类来获取数据库的连接,但是实际上是每次执行方法都新建一条连接(一般的方法流程是建立连接,执行sql,释放连接)。频繁的创建连接,和断开连接不仅麻烦,而且需要消耗的资源也很大。
我们可以使用连接池,来避免每个方法执行时都新建一条连接。连接池中有着多条已经建立好并且不会断开的连接,当方法或者说客户需要数据库连接时,就从连接池中获取一条连接,然后使用,使用完成后调用close方法。这里的close方法的作用不是关闭连接,而是将连接放回连接池,让其他客户使用。
连接池的原理是:
- 事先创建一个类似于JDBCUtil一样的工具类,这个工具类里面存放着连接池的信息。这些信息包括一个连接池的实例DataSource,连接池的大小,也就是最多可以存放多少条连接,以及连接数据库的各项信息。最后有一个方法,让外界可以调用这个方法从而获取连接池里面的连接。
- 当客户需要数据库连接时,先向连接池进行请求
(1)连接池中有空闲连接,则分配给客户使用,并将该连接置为“正在使用”状态 (2)连接池中没有空闲连接,则查看连接池的连接数是否超过最大值 ————(a)如果没超过,则创建一条新的连接,并返回给客户使用,并将该连接置为“正在使用”状态 ————(b)如果已经超过,则客户进入等待状态,超出等待时间则返回异常信息 (3)客户使用连接完毕后,调用close方法,将连接从“正在使用状态”置为“空闲状态”,从而让其他客户使用
使用连接池还有一个好处,如果在使用过程中,mysql数据库突然离线,那么以前的JDBCUtil数据库只会进行一次连接,连接断开也不会重新连接。而客户获取连接池中的连接时,如果连接断开,就会选择另外一条连接,并且尝试重新建立数据库的连接。
首先写一个测试类,来看一下连接池的运行过程
package com.demo.spring.test;
import org.apache.commons.dbcp2.BasicDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBCPTest {
public static void main(String[] args) throws SQLException {
BasicDataSource bds = new BasicDataSource();
bds.setInitialSize(5);
bds.setUrl("jdbc:mysql://master:3306/show1");
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUsername("root");
bds.setPassword("123456");
Connection connection = bds.getConnection();
PreparedStatement statement = connection.prepareStatement("select * from userInfo");
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()){
System.out.println(resultSet.getString("username"));
}
connection.close();
}
}
结果是正确的,成功获取了userInfo表里面的数据
写一个连接池的工具类,并且用这个工具类来修改Dao层的代码
package com.demo.spring.util;
import org.apache.commons.dbcp2.BasicDataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class DBCPUtil {
private static BasicDataSource bds;
static {
System.out.println("创建连接池");
bds = new BasicDataSource();
bds.setInitialSize(5);
bds.setUrl("jdbc:mysql://master:3306/show1");
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUsername("root");
bds.setPassword("123456");
}
public static Connection getConn(){
System.out.println("获取连接");
try {
return bds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
package com.demo.spring.mvc.dao;
import com.demo.spring.mvc.bean.User;
import com.demo.spring.util.DBCPUtil;
import com.demo.spring.util.JDBCUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserDao {
public User loginDao(String username){
User user = null;
try{
Connection conn = DBCPUtil.getConn();
String sql = "select * from userInfo where username=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,username);
ResultSet rs = ps.executeQuery();
if(rs.next()){
user=new User();
user.setId("id");
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
}
rs.close();
ps.close();
conn.close();
}catch (Exception e){
e.printStackTrace();
}
return user;
}
}
可以成功进行登录信息检查
之后每一次在浏览器的地址栏修改username和password,都会导致重新获取一次连接池中的连接
|