发表于: 2018-04-06 21:35:59

1 836


今天完成的事情:


1.继续完善学习数据库的连接(jdbc sql);

2.使用c3p0(单独使用类创建);

3.测试不关闭连接池,在main函数里循环调用1000次会出现什么情况;

4.测试db中断后的异常抓取。


1.学习更多的查询方法和其它增删改等

 jdbc查询集合,总数,orderby dese等,这里就不写了


2.使用类创建数据连接池


(可以直接使用xml文件,这里没有新建xml,直接使用的c3p0.properties.这样就需要一个一个get属性)

package mybatis.service;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

@Service
public class C3p0_Conn {

private static ComboPooledDataSource dataSource = null;
private static Properties properties = null;
//    private static C3p0_Conn c3p0_conn;

   static {

//        c3p0_conn = new C3p0_Conn();
       dataSource = new ComboPooledDataSource();
       properties = new Properties();

try {

//            properties.load(new FileInputStream("c3p0.properties"));
           properties.load(C3p0_Conn.class.getClassLoader().getResourceAsStream("c3p0.properties"));

//            System.out.print("\n\n===================\n" + properties.getProperty("driverClass") + "\n===================\n\n");

dataSource.setDriverClass(properties.getProperty("driverClass"));
dataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
dataSource.setUser(properties.getProperty("user"));
dataSource.setPassword(properties.getProperty("password"));

dataSource.setMaxPoolSize(Integer.parseInt(properties.getProperty("max_size")));
dataSource.setMinPoolSize(Integer.parseInt(properties.getProperty("min_size")));
dataSource.setInitialPoolSize(Integer.parseInt(properties.getProperty("initialPoolSize")));
dataSource.setMaxStatements(Integer.parseInt(properties.getProperty("max_statements")));
dataSource.setMaxIdleTime(Integer.parseInt(properties.getProperty("maxIdleTime")));

}catch (Exception e){
e.fillInStackTrace();
throw new ExceptionInInitializerError(e);
}
}

public Connection getConn(){
Connection conn = null;
try {
conn = dataSource.getConnection();
}catch (Exception e){
e.fillInStackTrace();
}
return conn;
}

public void closeConn(Connection conn){
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

}



3.不关闭连接池的情况下,在main函数里写1000次循环调用:


先测试循环‘关闭/连接’连接池5次:

public static void main(String[] args){

String sql = "select name from jnshu_user where id = ?";

C3p0_Conn c3p0_conn = new C3p0_Conn();
Connection conn = null;
PreparedStatement pstmt = null;
for (int i=0;i<5;i++){
try {

conn = c3p0_conn.getConn();
//                System.out.print("\n测试 ==" + sql + "==测试\n");
               pstmt = conn.prepareStatement(sql);
//                pstmt = (PreparedStatement) c3p0_conn.getConn().prepareStatement(sql);
               pstmt.setInt(1,i);
ResultSet resultSet = pstmt.executeQuery();
while (resultSet.next()){
logger.info("\n" + (i+1) + "次查询,名字为:" + resultSet.getString("name") + "\n");
}

pstmt.close();

resultSet.close();

} catch (SQLException e) {
e.printStackTrace();
logger.debug("\n查询数据库异常\n");
}finally {
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

}




循环‘关闭/连接’数据库,查询1000次(重复连接):



然后保持连接池连接再次测试:


第六次就结束了:


log调试信息:


[DEBUG] 2018-04-07 01:11:09,862 method:com.mchange.v2.log.slf4j.Slf4jMLog$Slf4jMLogger$DebugLogger.log(Slf4jMLog.java:204) 

acquire test -- pool size: 6; target_pool_size: 7; desired target? 7

[DEBUG] 2018-04-07 01:11:09,862 method:com.mchange.v2.log.slf4j.Slf4jMLog$Slf4jMLogger$DebugLogger.log(Slf4jMLog.java:204) 

获取测试——池大小:6


[DEBUG] 2018-04-07 01:14:54,771 method:com.mchange.v2.log.slf4j.Slf4jMLog$Slf4jMLogger$DebugLogger.log(Slf4jMLog.java:204)

acquire test -- pool is already maxed out[managed: 10; max: 10]

[DEBUG] 2018-04-07 01:14:54,772 method:com.mchange.v2.log.slf4j.Slf4jMLog$Slf4jMLogger$DebugLogger.log(Slf4jMLog.java:204)

提示“池已经刷爆了……”



然后就是等待,控制台一会儿开始输出:

[DEBUG] 2018-04-07 01:17:07,825 method:com.mchange.v2.log.slf4j.Slf4jMLog$Slf4jMLogger$DebugLogger.log(Slf4jMLog.java:204) 

BEGIN check for expired resources.  [com.mchange.v2.resourcepool.BasicResourcePool@5a61f5df]

检查过期资源……


这是测试的配置,其余都是默认

#初始化获得的连接
initialPoolSize = 100
#最大连接数
max_size = 10
#最大的PreparedStatement的数量
max_statements = 10
#最小连接数
min_size = 1
#当连接池中的连接耗尽的时候c3p0一次同时获取的连接数
acquireIncrement = 10
#定义在从数据库获取新连接失败后重复尝试的次数
acquireRetryAttempts = 10
#检查连接池里空闲连接的间隔 秒
idleConnectionTestPeriod = 60
#最大空闲时间,N秒内未使用则连接被丢弃。若为0则永不丢弃
maxIdleTime = 60
#两次连接间隔时间 毫秒
acquireRetryDelay = 1000
#连接关闭是否将未提交操作回滚 默认false
autoCommitOnClose = false


连接池已经满了


如果不关闭连接池的话,连接满了,就只能等待连接断掉再继续获取新的连接。就是相当于把连接池的连接拿出来,然后不归还,连接池就爆满了,然后就没办法继续获取连接了。


修改最大连接数

#初始化获得的连接
initialPoolSize = 100
#最大连接数
max_size = 500
#最大的PreparedStatement的数量
max_statements = 10
#最小连接数
min_size = 1
#当连接池中的连接耗尽的时候c3p0一次同时获取的连接数
acquireIncrement = 50

然后第142次的时候开始报错:



提示:


acquire test -- pool size: 142; target_pool_size: 142; desired target? 143

获取测试——池大小:142;target_pool_size:142;期望的目标?143


An exception occurred while acquiring a poolable resource. Will retry.

在获取可配置资源时发生了异常。将重试。


com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"

数据源拒绝建立连接,来自服务器的消息:“太多连接,超过最大连接数


重新关闭连接池,加大连接数,循环使用2s8ms。之前是40s





4.db断开连接后的异常抓取:



测试错误,错误代码行 resultSet为空集:

try {

conn = c3p0_conn.getConn();
//                System.out.print("\n测试 ==" + sql + "==测试\n");
               pstmt = conn.prepareStatement(sql);
//                pstmt = (PreparedStatement) c3p0_conn.getConn().prepareStatement(sql);
               pstmt.setInt(1,i);
ResultSet resultSet = pstmt.executeQuery();
while (resultSet.next()){
logger.info("\n" + (i+1) + "次查询,名字为:" + resultSet.getString("name") + "\n");
}

pstmt.close();

resultSet.close();

} catch (SQLException e) {
e.printStackTrace();
logger.debug("\n查询数据库异常\n");
}finally {
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

异常抓取(截图时使用的System.out.print输出):



断开数据库异常:

@Test
public void testDBClose(){

Connection connection = null;
PreparedStatement pstmt = null;
PreparedStatement pstmt2= null;
ResultSet resultSet = null;
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://119.29.17.188/jnshu";
String user = "root";
String password = "root";
String sql = "insert into person (name,age,sex,pro) values (?,?,?,?)";
String sqlselect = "select * from person ";
try {

Class.forName(driver);
connection = DriverManager.getConnection(url,user,password);
pstmt = connection.prepareStatement(sql);
pstmt2=connection.prepareStatement(sqlselect);
for(int i=0;i<5;i++){

User us1 = new User();

us1.setName( i + "师兄");
us1.setAge(i);
us1.setSex(1);
us1.setPro((i+1) + "师兄");

pstmt.setString(1,us1.getName());
pstmt.setInt(2,us1.getAge());
pstmt.setInt(3,us1.getSex());
pstmt.setString(4,us1.getPro());
logger.info(String.valueOf(pstmt.executeUpdate()));
resultSet = pstmt2.executeQuery();
while (resultSet.next()){
logger.info("\n" + resultSet.getString("name") + "\n");
}

           System.out.print("\n=====================\n");


if (i==3){
               connection.close();
           }


}

if (connection != null){
connection.close();
}

pstmt.close();


} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
       System.err.print("\n数据库断开连接\n");
e.printStackTrace();
}


}

异常提示:




关于插入百万数据:

这是之前插入的数据,今天查的一共409万2911条,未加索引,执行了大半天。嗯……不到一天。如果执行的时候还要继续加索引,时间会更长。但是相对的查询时间会更少。



明天计划的事情:



1.继续学习java基础和SQL语句


2.测试索引相关


3.配置日志问题,看能不能只输出重要的需要的信息


遇到的问题和收获:


1.prepareStatement的Updata方法和Query方法返回值的问题,ResultSet集合为空。

解决:正常使用就行了……

2.properties.load(C3p0_Conn.class.getClassLoader().getResourceAsStream("c3p0.properties"));

读取文件的问题,配置文件

解决:添加C3p0_Conn.class.getClassLoader() 或者使用xml在同级目录下配置

3.数据池的连接问题(c3p0一些属性)

4.查询返回值,同1

5.异常的处理 try/catch/throw/throws










返回列表 返回列表
评论

    分享到