数据库连接池
1、为什么要使用连接池?
数据源:数据的来源----mysql
连接池:连接管理复用机制
为什么合起来称呼,因为在我们当前机制下,就是通过连接池完成数据源的操作的
我们现在使用数据库,都是在需要使用的时候开始建立连接,等到我们使用完之后,就会把这连接close(回收释放断开销毁),等到我们又需要连接数据库时,就。。。。。。。。。。。。。
连接是给我们提供数据服务的,我们可以把它看成我们的10086移动客服业务,我们现在的做法,等同于-à有客户来咨询-à发现需要使用客服人员-à招聘培训上岗一个客户人员提供服务-à客户咨询完毕后,把这个培训人员close -à又有个客户来咨询.........
解决建立数据库连接耗费资源和时间很多的问题,提高性能。
2、打造自己的的数据源连接池
1)编写自己的配置文件(mypoolconfig.properties)
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/java1_9
username=root
password=123456
#
initialSize=1
#最大连接数量
maxActive=5
#
maxIdle=2
#
minIdle=1
#
maxWait=60000
2)编写自己的配置文件加载类
public classPoolConfig {
public static String DRIVER_NAME = null;
public static String CONN_URL = null;
public static String ACCOUNT = null;
public static String PWD = null;
public static int INITIAL_SIZE = 1;
public static int MAXACTIVE = 1;
public static int MAXIDLE = 1;
public static int MINIDLE = 1;
public static void loadConfig(Propertiesproperties){
DRIVER_NAME=properties.getProperty("driverClassName");
CONN_URL=properties.getProperty("url");
ACCOUNT=properties.getProperty("username");
PWD=properties.getProperty("password");
INITIAL_SIZE=Integer.parseInt(properties.getProperty("initialSize"));
MAXACTIVE=Integer.parseInt(properties.getProperty("maxActive"));
MAXIDLE=Integer.parseInt(properties.getProperty("maxIdle"));
MINIDLE=Integer.parseInt(properties.getProperty("minIdle"));
}
}
3)在写自己的连接池适配类,为了获取到我们需要的方法!
public abstract class PoolWrapper implements DataSource{
@Override
publicConnection getConnection(String username, String password) throws SQLException{
returnnull;
}
@Override
public
returnnull;
}
@Override
public booleanisWrapperFor(Class> iface) throws SQLException {
returnfalse;
}
@Override
publicPrintWriter getLogWriter() throws SQLException {
returnnull;
}
@Override
public voidsetLogWriter(PrintWriter out) throws SQLException {
}
@Override
public voidsetLoginTimeout(int seconds) throws SQLException {
}
@Override
public intgetLoginTimeout() throws SQLException {
return 0;
}
@Override
public LoggergetParentLogger() throws SQLFeatureNotSupportedException {
returnnull;
}
}
4) 编写连接工具类(作用就是加载驱动,获取连接)
public class UtilConn {
static {
try {
Class.forName(PoolConfig.DRIVER_NAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException("驱动加载错误!");
}
}
public static Connection openConnection() {
Connection connection = null;
try {
connection =DriverManager.getConnection(PoolConfig.CONN_URL, PoolConfig.ACCOUNT,PoolConfig.PWD);
} catch (SQLException e) {
throw new RuntimeException("数据库连接错误!");
}
return connection;
}
public static void release(Connection connection , Statement statement,ResultSet resultSet){
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void release(Connection connection , Statement statement){
release(connection,statement,null);
}
public static void release(Connection connection){
release(connection,null,null);
}
}
5) 最后编写自己的连接池,继承上面的连接池适配类(单例模式)
public class Pool extends PoolWrapper {
private staticPool pool;
//存放我们所有实例化出来的,没有在使用的Connection对象
private staticLinkedList
//记录我们当前已经产生过多少个连接对象了,为什么不使用connections.size()?
private staticint connTotalCount = 0;
private Pool(){
}
//单例--连接池有一个就够了,提供多个连接对象
public staticDataSource createDataSource(Properties properties) {
if (pool ==null) {
pool =new Pool();
PoolConfig.loadConfig(properties);
for(int i = 0; i < PoolConfig.INITIAL_SIZE; i++) {
Connection connection =UtilConn.openConnection();
connections.add(connection);
}
connTotalCount = PoolConfig.INITIAL_SIZE;
}
returnpool;
}
//提供连接
@Override
publicConnection getConnection() throws SQLException {
//移除栈顶元素,返回值是我们刚刚移除出来的对象
Connectionconnection = connections.pop();
//如果获取一个连接之后,不满足最小空闲连接限制,则新增一个
if(connections.size() < PoolConfig.MINIDLE) {
//并且没有超出我们的连接总数上限
if (connTotalCount< PoolConfig.MAXACTIVE) {
connections.add(UtilConn.openConnection());
connTotalCount++;
}
}
if(connection == null) {
thrownew RuntimeException("连接全忙,请稍后访问!!!");
}
returnconnection;
}
//回收连接
public staticvoid recycleConnection(Connection connection) {
if(connections.size() < PoolConfig.MAXIDLE) {
connections.add(connection);
} else {
UtilConn.release(connection);
}
}
}
3、常用的数据源配置(日后都使用数据源,一定要配置一下)
3.1、DBCP
DBCP:Apache推出的Database Connection Pool
使用步骤:
> 添加jar包 commons-dbcp-1.4.jar commons-pool-1.5.6.jar
> 添加属性资源文件
> 编写数据源工具类
publicclass UtilDBCP {
private static DataSource dataSource;
//声明一个连接池
static {
Properties properties=new Properties();
InputStream inputStream =UtilDBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
try {
dataSource =BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//打开一个连接
public static Connection openConn(){
try {
return dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
throw new RuntimeException("无法获取连接!");
}
public static void release(Connectionconnection , Statement statement, ResultSet resultSet){
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void release(Connectionconnection , Statement statement){
release(connection,statement,null);
}
public static void release(Connectionconnection){
release(connection,null,null);
}
}
3.2、C3P0
使用步骤:
1、添加jar包
2、编写配置文件
c3p0-config.xml,放在classpath中,或classes目录中
3、编写工具类:(释放连接跟上面步骤一样)
publicclass UtilC3P0 {
private static ComboPooledDataSourcecomboPooledDataSource;
static {
comboPooledDataSource=new ComboPooledDataSource();
}
public static Connection openConn(){
try {
returncomboPooledDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
throw new RuntimeException("无法获取连接!");
}
4、用JavaWeb服务器管理数据源:Tomcat(已经测试会出错,没法查明原因)
开发JavaWeb应用,必须使用一个JavaWeb服务器,JavaWeb服务器都内置数据源。
Tomcat:(DBCP)
数据源只需要配置服务器即可。
配置数据源的步骤:
1、拷贝数据库连接的jar到tomcatlib目录下
2、配置数据源XML文件
a)如果把配置信息写在tomcat下的conf目录的context.xml中,那么所有应用都能使用此数据源。
b)如果是在当前应用的META-INF中创建context.xml, 编写数据源,那么只有当前应用可以使用。
maxActive="100"maxIdle="30" maxWait="10000"
username="root"password="123456" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test2"/>
3、使用连接池