1.连接池
jdbc2.0才引进连接池(连接池的技术标准就是DataSource替代DriverManager)
2.c3p0连接池
package com.itheima04.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class C3p0Demo {
public static void main(String[] args) throws PropertyVetoException, SQLException {
// method01(); //这行方法和下面xml文件无关
/*
* 配置文件方式 :
* 默认情况下, c3p0将会在 类加载器路径(在当前的工程下, src路径)下
* 寻找一个名为c3p0-config.xml 配置文件(xml文件是复杂的Properties文件,也是key-value)
*
* 套路:
* 1. 在src下创建名为c3p0-config.xml配置文件(内容直接复制)
* 2. 创建ComboPooledDataSource核心类
*
* 原理:
* 1. 底层自动会去类加载器路径(写代码:src下) 去寻找一个名为c3p0-config.xml 配置文件
* 2. 自动解析: 读取xml中配置信息 , 设置给c3p0即cpds
*/
ComboPooledDataSource cpds = new ComboPooledDataSource(); //自动设置cpds.set
String sql = "select * from account"; // 同下面
Connection conn = cpds.getConnection();
PreparedStatement pstm = conn.prepareStatement(sql);
ResultSet resultSet = pstm.executeQuery();
while(resultSet.next()){
String name = resultSet.getString("name");
System.out.println(name + "--");
}
conn.close();// 将连接还给连接池
cpds.close(); // 销毁
}
//1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
private static void method01() throws PropertyVetoException, SQLException {
// 如下硬编码: 用代码来实现参数的设置。一般不用硬编码,用配置文件
ComboPooledDataSource cpds = new ComboPooledDataSource();//ComboPooledDataSource是DataSource实现类
cpds.setDriverClass( "com.mysql.jdbc.Driver"); //需要mysql-connector-java-x.x.x-bin.jar
cpds.setJdbcUrl( "jdbc:mysql://localhost:3306/day05" );
cpds.setUser("root");
cpds.setPassword("1234");
String sql = "select * from account";
Connection conn = cpds.getConnection();
PreparedStatement pstm = conn.prepareStatement(sql);
ResultSet resultSet = pstm.executeQuery();
while(resultSet.next()){
String name = resultSet.getString("name");
System.out.println(name); //System.err.println(name);//红色
}
conn.close();// 将连接还给连接池
cpds.close(); // 销毁
}
}
<!-- c3p0-config.xml -->
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day05</property>
<property name="user">root</property>
<property name="password">1234</property>
<!-- 连接池参数 -->
<!--
initialPoolSize : 初始化连接数 3
maxPoolSize: 最大连接数 5
checkoutTimeout : 连接超时时间 2000ms(默认10s,访问数超过最大连接数, 有人必须要等,2秒连不上给个提示或报错)
maxIdleTime :最大的闲置时间,连接超过maxIdleTime没人使用闲置就销毁maxPoolSize中连接,留到minPoolSize中数量,因为费内存
-->
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">5</property>
<property name="minPoolSize">2</property>
<property name="checkoutTimeout">2000</property>
<property name="maxIdleTime">1000</property>
</default-config>
<named-config name="xx">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/beitai</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">15</property>
<property name="checkoutTimeout">2000</property>
<property name="maxIdleTime">1000</property>
</named-config>
</c3p0-config>
3.类加载器路径
package com.itheima04.c3p0;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ParseDemo {
@Test
public void method01() throws IOException {
Properties p = new Properties(); //Properties就是一个map
p.load(new FileInputStream("src/jdbc.properties")); //相对路径:当前工程src下
String url = p.getProperty("url"); //.properties文件中有url=...
System.out.println(url);
}
@Test
public void method02() throws IOException {
/*
* 1. 类加载器 classloader
* 作用: 将 .class文件(硬盘) 加载进内存(兼职把jdbc.properties加载进来)。底层: 输入流
*
* 2. 怎么知道.class文件在哪里?
* 有个默认加载路径:out路径下项目名路径(src和out/production/项目名路径里文件全一样)。
*
* method02通用,因为每个工程都会有类加载器路径,但是每个工程的相对路径不一定是当前工程src下。
* web阶段main方法不在项目里,每个项目的入口是main方法,main方法在tomcat里,
* 所以工程的相对路径会变,但是类加载器的路径不变,一直指向.class文件路径。
*/
ClassLoader classLoader = ParseDemo.class.getClassLoader(); //利用当前类获取类加载器路径
InputStream is = classLoader.getResourceAsStream("jdbc.properties");// 获取资源转成流 , 相对路径: out/production/jdbc-day05,这路径称为类加载器路径
Properties p = new Properties();
p.load(is);
String url = p.getProperty("url");
System.out.println(url + "-2");
}
}
如上两个方法都输出如下
4.c3p0-config.xml验证
package com.itheima04.c3p0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class C3p0Demo02 {
public static void main(String[] args) throws SQLException {
// ComboPooledDataSource ds = new ComboPooledDataSource(); //使用默认配置即c3p0-config.xml中<default-config>
// ComboPooledDataSource ds = new ComboPooledDataSource("xx"); //使用命名配置即c3p0-config.xml中<named-config name="xx"> //备胎项目用。
//循环模拟: 有几多个用户
for (int i = 0; i < 6; i++) {
Connection conn = ds.getConnection();
System.out.println(conn); //没有下面close,5个连接6个人拿超过2s,会发生timed out报错
if(i == 3){
//i=3打印了下又还给连接池,所以i=3打印了两次。
conn.close(); //验证了确实连接还给连接池
}
}
}
}
5个连接6个人拿是不够的。如下最后@2d…打印了2次并且没有发生timed out连接超时错误。
5.druid连接池
package com.itheima05.druid;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class DruidDemo {
public static void main(String[] args) throws Exception {
// method01();
//如下配置文件的方式
InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
Properties p = new Properties();
p.load(is);
//自动解析.properties文件,不用getProperty
DataSource ds = DruidDataSourceFactory.createDataSource(p);
String sql = "select * from account";
Connection conn = ds.getConnection(); //获取连接
PreparedStatement pstm = conn.prepareStatement(sql);
ResultSet resultSet = pstm.executeQuery();
while(resultSet.next()){
String name = resultSet.getString("name");
System.out.println(name + "-++");
}
conn.close();// 将连接还给连接池
}
//111111111111111111111111111111111111111111111111111111111111111111111111
private static void method01() throws SQLException {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql:///day05");
ds.setUsername("root");
ds.setPassword("1234");
String sql = "select * from account";
Connection conn = ds.getConnection();
PreparedStatement pstm = conn.prepareStatement(sql);
ResultSet resultSet = pstm.executeQuery();
while(resultSet.next()){
String name = resultSet.getString("name");
System.out.println(name + "--");
}
conn.close();// 将连接还给连接池
// ds.close(); // 销毁 //实际开发服务器不关,连接池不会销毁
}
}
//druid.properties文件,如下key固定写法
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///day05
username=root
password=1234
6.封装druid连接池工具类
File-New-Project-Java
package com.itheima.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JdbcUtil {
private static DataSource ds; //下面getConn()也能访问到
static{
//静态代码块只运行一次
try {
Properties p = new Properties();
InputStream is = JdbcUtil.class.getClassLoader().getResourceAsStream("druid.properties");
p.load(is);
//DataSource ds = 移到最上面了
ds = DruidDataSourceFactory.createDataSource(p);
} catch (Exception e) {
e.printStackTrace();
}
}
//11111111111111111111111111111111111111111111111111111111111111111111111111
public static DataSource getDs() {
//属性私有化后提供对外公开的方法
return ds;
}
//11111111111111111111111111111111111111111111111111111111111111111111111111
public static Connection getConn() throws SQLException {
// Connection connection = ds.getConnection();
// return connection;
return ds.getConnection(); //等同上面两行
}
//11111111111111111111111111111111111111111111111111111111111111111111111111
public static void release(AutoCloseable... ios){
for (AutoCloseable io : ios) {
if(io != null){
try {
io.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
package com.itheima.utils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//测试上面JdbcUtil类
public class TestDemo {
@Test
public void method01() throws SQLException {
String sql = "select * from account";
//封装了1,2,6步骤。3,4,5没有封装
Connection conn = JdbcUtil.getConn();
PreparedStatement pstm = conn.prepareStatement(sql);
ResultSet resultSet = pstm.executeQuery();
while(resultSet.next()){
String name = resultSet.getString("name");
System.out.println(name);
}
JdbcUtil.release(resultSet,pstm,conn); //注意: conn的close是将连接还给连接池
}
}
如下是数据库中name这一列,不是.properties文件的key。
B站/知乎/微信公众号:码农编程录