最近遇到的连接问题我准备从重构的几个程序(redis和mysql)长连接和短连接,以及连接池和单连接等问题用几篇博客来总结下。
这个问题的具体发生在java原生程序和mysql的交互中。心得和上一篇一样,不过没用好也有对连接池的不熟悉的原因,连接池本身的api和配置项,以及与一些框架的集合仍然是值得研究的问题(这次因为方向问题先回避了)。
应用场景2
java原生程序,内部写多个线程,均会产生mysql的数据输出。
开始直接使用durid连接池获取连接,但在程序的运行过程中连接会掉,且不会抛出异常,但却导致程序卡住,逻辑功能出现异常。
最开始是想通过在配置文件中配置自动连接和重连接,但是该项配置没有起作用。
尝试过的配置(失败的带研究的配置):
druid.url=jdbc:mysql://0.0.0.0:3306/test?useUnicode=yes&characterEncoding=UTF-8&autoReconnect=true
后面采用获取短连接的方式,在执行业务后关闭连接。
然后因为业务的简便性更进一步采用单连接的方式处理了该问题。其中核心仍然是不断初始化对象获取连接和关闭连接。修改后基本utils代码如下
public class JDBCUtil {
//JDBC驱动
private static String jdbcDriver = "com.mysql.jdbc.Driver";
//数据库用户名
private static String username = "mysql";
//数据库密码
private static String password = "123456";
//数据库连接字符串
private static String connStr = "jdbc:mysql://0.0.0.0:3306/test";
private Connection conn;
public JDBCUtil(){
try {
getConnect();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 连接数据库
*
* @throws SQLException
*/
public Connection getConnect() throws Exception {
Class.forName(jdbcDriver);
conn = DriverManager.getConnection(connStr, username, password);
return conn;
}
/**
* 关闭数据库,释放内存
*
* @throws SQLException
*/
public void close() throws SQLException {
if (conn != null) {
conn.close();
}
}
/**
* 设置PrepareStatement对象中Sql语句中的参数
*
* @param sql sql语句
* @param params 参数列表
* @throws SQLException
*/
@SuppressWarnings("unused")
private PreparedStatement setPrepareStatementParams(String sql, Object[] params) throws SQLException {
PreparedStatement pstm = conn.prepareStatement(sql);
if (params != null) {
for (int i = 0; i < params.length; i++){
pstm.setObject(i + 1, params[i]);
}
}
return pstm;
}
/**
* 执行查询
*
* @param sql sql语句
* @param params 参数列表
* @return 返回ResultSet类型的查询结果
* @throws SQLException
*/
public ResultSet executeQuery(String sql, Object[] params) throws Exception {
PreparedStatement pstm = setPrepareStatementParams(sql, params);
ResultSet rs = pstm.executeQuery();
return rs;
}
/**
* 更新数据库操作
*
* @param sql sql语句
* @param params 参数列表
* @return 执行操作的结果
* @throws SQLException
*/
public void executeUpdate(String sql, Object[] params) throws Exception {
setPrepareStatementParams(sql, params).executeUpdate();
}
}
其他问题
第一次重写方法的时候,我采用了静态类和单例模式,直接导致我两个线程之间创建连接出现冲突。这在java多线程的使用中应该值得注意。