概述
JDBC连接池
- 抛砖引玉
- 连接池
- 创建连接池
- 连接池的优化
- Properties类助力连接池
- 构造方法
- 常用方法
- 配置文件读取时常见的问题汇总----
抛砖引玉
我们在谈论**"池"什么时候是什么时间?我记得上一次是IO流的时候,建立缓冲池,加快读取速度/写入速度(实际是减少IO 操作次数)
那么什么时候会用到连接池呢???
连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。
连接池
这就要从java工具类来讲,java功能工具类为我们的开发提供了便利,同理连接池正式基于这种理念进行设计的;
对于大多数客户端请求,进行数据库的相关事务时,仅需要能够访问JDBC连接的 1 个线程。当客户端不需要处理事务时,那么这个连接就会闲置。
这样如果有很多客户端来请求,那么闲置的连接能不能被再次使用呢?
答案是可以的,这样就减少了资源的消耗(当客户端请求时,用已经闲置的连接就可以了),加快了客户端请求的速度;
使用连接池技术能够降低资源消耗,使得cpu能过够更多的用于别的事务;
下面来模拟一个连接缓冲池
创建连接池
连接池的大体描述------
假设这样一个场景,一所学校的选课系统,平时选课系统的并发量很少,只有学期开始选课的时候,并发量才上去了;
我记得当时我们学校(别问哪个学校,反正不是你学校)的限制是同时500人可以进行选课;一个人释放该链接的时候下一个人才能连接到选课系统;
下面开始干活-------
public class MyConnection {
//准备连接用的
final static String URL = "jdbc:mysql://127.0.0.1:3306/gavin?";
final static String USER = "gavin";
final static String PASSWORD = "root";
//准备一个池子用于盛放连接
private static LinkedList<Connection> pool;
//初始化大小
private static int initSize = 5;
//限制池子的最大大小
private static int maxSize = 10;
//加载该连接池类信息时就初始化了pool,pool中存放了5个连接实例
static {
//加载驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//开辟空间用于初始化连接池
pool = new LinkedList<Connection>();
//往池子中添加5个连接实例
for (int i = 0; i < initSize; i++) {
Connection connection = initConnection();
pool.addLast(connection);
}
}
//初始化一个connection;
public static Connection initConnection(){
Connection connection = null;
try {
connection=DriverManager.getConnection(URL, USER, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
System.out.println("异常");
}
return connection;
}
//用于获得连接的方法
public static Connection getConnection() {
//怎么获得呢?
//当连接池中有连接的时候,直接从里面取用
Connection connection;
if (pool.size() != 0) {
connection = pool.removeFirst();
System.out.println("连接池中--"+connection.hashCode()+"被取走了");
} else {//当连接池中没有的时候,创建一个
connection = initConnection();
System.out.println("连接池已空--"+connection.hashCode()+"被创建了");
}
return connection;
}
//用户还回去的方法
public static void returnConnection(Connection connection){
//什么时候往回还,要求池子内少于五个的时候我才接收
//检测
if(null!=connection) {//不为空
try {//检测
if (!connection.isClosed()) {//连接未关闭的话
//检测
//如果池子中少于10个则可以添加进去--始终保证最大化缓冲池
if (pool.size() <= maxSize) {
//向池中增加该连接
connection.setAutoCommit(true);
pool.addLast(connection);//
System.out.println("归还的连接"+connection.hashCode()+"符合要求,归还成功");
}else{//如果归还后池子中连接数大于10,则将该链接关闭
System.out.println("池子中已满"+connection.hashCode()+"--将被关闭");
connection.close();
}
}else{//连接关闭
System.out.println("归还的连接不能使用,归还失败");
}
} catch (SQLException e) {
e.printStackTrace();
}
}else{
System.out.println("归还失败");
}
}
public static void main(String[] args) {
Connection connection = getConnection();
Connection connection1 = getConnection();
try {
connection1.close();
} catch (SQLException e) {
e.printStackTrace();
}
getConnection();
getConnection();
getConnection();
getConnection();
returnConnection(connection);
returnConnection(null);
returnConnection(connection1);
}
}
测试结果如下-----
要考虑连接池的健壮性,同时要考虑服务器的承压情况,灵活调整连接池中连接的数量;
连接池的优化
关于连接池的优化,当前代码有一个小小的问题,当我们要设置池的大小的之时,或者修改要连接的数据库时,我们就要停止代码的运行,然后修改,那么为了优化这一点就产生了相应的优化方案----
将这些数据单独妨碍一个配置文件中进行存放,如果哪一天要修改,在配置文件中修改就可以了;
关于配置文件的读取,Java中有一个专门的类用于读取配置文件,在util包下-----Properties
先来看一下该类—
Properties类助力连接池
public class Properties extends Hashtable<Object,Object>
是Hashtable 的子类,以键值对的方式存储数据;
该类表示一组恒久的属性。可以保存到流或从流加载。属性列表中的每个密钥及其相应值均为字符串。
此类是线程安全的:多个线程可以共享单个对象,而无需外部同步。Properties
构造方法
Properties()
创建没有默认值的空属性列表。
Properties(int initialCapacity)
创建没有默认值的空属性列表,初始大小可容纳指定数量的元素,无需动态调整大小。
Properties(Properties defaults)
使用指定的默认值创建空属性列表。
常用方法
可以试着建立一个jdbc.properties文件,
文件内容------
文件内容格式----## 表示注释
文件内内容均默认为文本格式, 具体化格式是 key=value
建一个测试类-----
package com.gavin.dao;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class TestProperties {
public static void main(String[] args) {
Properties properties= new Properties();//实力话配置实例
/**
* 怎么导入呢?
* 获取配置文件位置,怎么或获取呢?
* 通过当前类的字节码文件来获得一个输入流然后通过输入流将配置文件给加载进来
* 注意文件路径的格式---- /相对路径(最好是相对路径)
*/
InputStream resourceAsStream = TestProperties.class.getResourceAsStream("/jdbc.properties");
try {
properties.load(resourceAsStream);
} catch (IOException e) {
e.printStackTrace();
}
String user = properties.getProperty("USER");
System.out.println(user);
}
}
配置文件读取时常见的问题汇总----
1. 获取的结果为null
原因-----代码中要获取的key与配置中的key名称不配写不匹配(大小写),不要有不该有的空格
2,Exception in thread “main” java.lang.NullPointerException: inStream parameter is null
说明配置文件输入流为空-----
可能是配置文件名或者地址写错了
连接池的具体优化—
package com.gavin.dao;
import com.gavin.UtilTool;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
public class MyConnection {
//准备连接用的
private static String DRIVER ;
private static String URL ;
private static String USER;
private static String PASSWORD ;
//准备一个池子用于盛放连接
private static LinkedList<Connection> pool;
//初始化大小
private static int initSize ;
//限制池子的最大大小
private static int maxSize ;
//加载该连接池类信息时就初始化了pool,pool中存放了5个连接实例
static {
UtilTool utool= new UtilTool("/jdbc.properties");
DRIVER = utool.getProperties("DRIVER");
URL = utool.getProperties("URL");
USER = utool.getProperties("USER");
PASSWORD= utool.getProperties("PASSWORD");
initSize=Integer.parseInt(utool.getProperties("iniSize"));
maxSize=Integer.parseInt(utool.getProperties("maxSize"));
//加载驱动
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//开辟空间用于初始化连接池
pool = new LinkedList<Connection>();
//往池子中添加5个连接实例
for (int i = 0; i < initSize; i++) {
Connection connection = initConnection();
pool.addLast(connection);
}
}
//初始化一个connection;
public static Connection initConnection(){
Connection connection = null;
try {
connection=DriverManager.getConnection(URL, USER, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
System.out.println("异常");
}
return connection;
}
//用于获得连接的方法
public static Connection getConnection() {
//怎么获得呢?
//当连接池中有连接的时候,直接从里面取用
Connection connection;
if (pool.size() != 0) {
connection = pool.removeFirst();
System.out.println("连接池中--"+connection.hashCode()+"被取走了");
} else {//当连接池中没有的时候,创建一个
connection = initConnection();
System.out.println("连接池已空--"+connection.hashCode()+"被创建了");
}
return connection;
}
//用户还回去的方法
public static void returnConnection(Connection connection){
//什么时候往回还,要求池子内少于五个的时候我才接收
//检测
if(null!=connection) {//不为空
try {//检测
if (!connection.isClosed()) {//连接未关闭的话
//检测
//如果池子中少于10个则可以添加进去--始终保证最大化缓冲池
if (pool.size() <= maxSize) {
//向池中增加该连接
connection.setAutoCommit(true);
pool.addLast(connection);//
System.out.println("归还的连接"+connection.hashCode()+"符合要求,归还成功");
}else{//如果归还后池子中连接数大于10,则将该链接关闭
System.out.println("池子中已满"+connection.hashCode()+"--将被关闭");
connection.close();
}
}else{//连接关闭
System.out.println("归还的连接不能使用,归还失败");
}
} catch (SQLException e) {
e.printStackTrace();
}
}else{
System.out.println("归还失败");
}
}
public static void main(String[] args) {
Connection connection = getConnection();
Connection connection1 = getConnection();
try {
connection1.close();
} catch (SQLException e) {
e.printStackTrace();
}
getConnection();
getConnection();
getConnection();
getConnection();
returnConnection(connection);
returnConnection(null);
returnConnection(connection1);
}
}
查看,功能正常–说明配置文件成功
同时我们还可以查看配置文件和代码中相关参数的颜色
最后
以上就是魁梧香菇为你收集整理的jdbc配置文件---NullPointerException: inStream parameter is null异常解决抛砖引玉连接池的全部内容,希望文章能够帮你解决jdbc配置文件---NullPointerException: inStream parameter is null异常解决抛砖引玉连接池所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复