当前位置:   article > 正文

Junit Test异常:java.sql.SQLNonTransientConnectionException: No operations allowed after con

java.sql.sqlnontransientconnectionexception: no operations allowed after con

场景:一个Test类中有两个或以上的处理数据库DML语句

原因:出现这种异常的原因是,正规的mysql 操作DML语句都是执行Connection取到数据后,就执行JDBCUtils.close(con, pst, rs) ,而test自动化单元测试(mvn clean test  ||  mvn test)时,会在一个单元测试类中执行多次DML语句。当第一次释放资源后,第二次再去连接数据库就会出现这样的异常报错。【注:一个类只有一个DML语句操作的test时请绕过】

  1. package com.kmt.bkm.server.Utils.sql;
  2. import java.sql.*;
  3. /*
  4. * 实现JDBC的工具类
  5. * 定义方法,直接返回数据库的连接对象
  6. *
  7. * 写关闭方法
  8. */
  9. public class JDBCUtils {
  10. private static Connection con;
  11. static {
  12. try{ //useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=CTT&autoReconnect=true
  13. String url = "jdbc:mysql:localhost/库Name?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&autoReconnect=true";
  14. String username = "root";
  15. String password = "root";
  16. //根据版本去使用对应的数据库驱动
  17. // Class.forName("com.mysql.jdbc.Driver"); //6.0版本以前
  18. Class.forName("com.mysql.cj.jdbc.Driver"); //6.0版本以后
  19. con = DriverManager.getConnection(url, username, password);
  20. } catch (Exception ex) {
  21. throw new RuntimeException(ex + "数据库连接失败");
  22. }
  23. }
  24. /*
  25. * 返回数据库的连接对象
  26. */
  27. public static Connection getConnection() {
  28. return con;
  29. }
  30. public static void close(Connection con, Statement stat) {
  31. if (stat != null) {
  32. try {
  33. stat.close();
  34. } catch (SQLException ex) {
  35. }
  36. }
  37. if (con != null) {
  38. try {
  39. con.close();
  40. } catch (SQLException ex) {
  41. }
  42. }
  43. }
  44. public static void close(Connection con, Statement stat, ResultSet rs) {
  45. if (rs != null) {
  46. try {
  47. rs.close();
  48. } catch (SQLException ex) {
  49. }
  50. }
  51. if (stat != null) {
  52. try {
  53. stat.close();
  54. } catch (SQLException ex) {
  55. }
  56. }
  57. if (con != null) {
  58. try {
  59. con.close();
  60. } catch (SQLException ex) {
  61. }
  62. }
  63. }
  64. /**
  65. * 获取MySql的版本
  66. * @return
  67. * @throws SQLException
  68. */
  69. public static Integer sqlVersion() throws SQLException {
  70. DatabaseMetaData metaData = (DatabaseMetaData) con.getMetaData();
  71. String version = metaData.getDatabaseProductVersion(); //得到数据库版本信息
  72. Integer ver = Integer.valueOf(version.substring(0 ,1));
  73. return ver;
  74. }
  75. public static void main(String str[]) throws SQLException {
  76. DatabaseMetaData metaData = (DatabaseMetaData) con.getMetaData();
  77. String version = metaData.getDatabaseProductVersion(); //得到数据库版本信息
  78. System.out.println("-----> " + version.substring(0 ,1));
  79. }
  80. }

一般流程:

  1. /**
  2. * 获取数据库中的商家id
  3. * @param limit 需要查几条
  4. * @return
  5. * @throws SQLException
  6. */
  7. public ArrayList<Long> getCustomerIdByDB(int limit) throws SQLException {
  8. ArrayList<Long> customerList = new ArrayList<>();
  9. String sql = "SELECT * FROM cct_customer ORDER BY id ASC LIMIT " + limit + ";";
  10. //获取数据库连接对象
  11. Connection con = JDBCUtils.getConnection();
  12. //获取sql语句执行者对象
  13. PreparedStatement pst = (PreparedStatement) con.prepareStatement(sql);
  14. //调用查询方法获得结果集
  15. ResultSet rs = pst.executeQuery();
  16. //所需取值Object定义
  17. Long sid;
  18. while (rs.next()) {
  19. //获取每个列的数据,封装到Product对象中
  20. sid = rs.getLong("id");
  21. //把封装好的Product对象存储到list中
  22. customerList.add(sid);
  23. }
  24. //查询完成释放资源
  25. JDBCUtils.close(con , pst , rs);
  26. if (null != customerList && customerList.size() > 0)
  27. return customerList;
  28. else
  29. return null;
  30. }

解决方法:建立常链接(优缺点我不太清楚,只是单纯的解决异常),把Connection ,PreparedStatement,ResultSet定义为全局变量,如下所示

  1. public class Test{
  2. //获取数据库连接对象
  3. static Connection con;
  4. PreparedStatement pst;
  5. ResultSet rs;
  6. static {
  7. //Connection实例化方式一
  8. con = JDBCUtils.getConnection();
  9. }
  10. @Before
  11. public void before(){
  12. //Connection实例化方式二
  13. con = JDBCUtils.getConnection();
  14. }
  15. @After
  16. public void after(){
  17. JDBCUtils.close(con, pst, rs);
  18. }
  19. @Test
  20. public void testDemo1(){
  21. //DML处理1
  22. //todo
  23. }
  24. @Test
  25. public void testDemo2(){
  26. //DML处理2
  27. //todo
  28. }
  29. }

好了,就是这么处理的,如果处理方法有问题,欢迎大佬留言其他处理方法或者优缺点的理论

文章参考:https://www.cqmaple.com/201308/no-operations-allowed-after-connection-closed.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/591123
推荐阅读
相关标签
  

闽ICP备14008679号