关于Java出现No operations allowed after connection closed.错误的原因和自己的理解
连接数据库时的代码
public class DataAccess {
private static Connection conn = null;
/**
* 连接数据库
* @return
*/
public static Connection getConnection() {
if(conn == null) {
//载入驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//定义URL连接
String url = "jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8&useSSL=false&useUnicode=true&characterEncoding=UTF-8";
//建立连接
conn = DriverManager.getConnection(url, "root", "123456");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
return conn;
}
/**
* 关闭有结果集的数据库连接
* @param conn
* @param stat
* @param rs
*/
public static void closeConnection(Connection conn,PreparedStatement stat,ResultSet rs) {
try {
if(rs != null) {
rs.close();
}
if(stat != null) {
stat.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 关闭没有结果集的数据库连接
* @param conn
* @param stat
*/
public static void closeConnection(Connection conn,PreparedStatement stat) {
try {
if(stat != null) {
stat.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
调用数据库进行查询或更新代码块
@Override
public List<User> findAllUser() {
PreparedStatement stat = null;
ResultSet rs = null;
Connection conn = null;
String sql = "SELECT * FROM `user`;";
conn = DataAccess.getConnection();
try {
stat = conn.prepareStatement(sql);
rs = stat.executeQuery();
List<User> list = new ArrayList<User>();
while(rs.next()) {
User user = new User();
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
user.setBirth(rs.getDate("birth"));
list.add(user);
}
return list;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DataAccess.closeConnection(conn, stat, rs);
}
return null;
}
@Override
public int upDateUser(User user) {
PreparedStatement stat = null;
Connection conn = null;
String sql = "update User set password=?,email=?,birth=? where name=? ;";
conn = DataAccess.getConnection();
try {
stat = conn.prepareStatement(sql);
stat.setString(1, user.getPassword());
stat.setString(2, user.getEmail());
stat.setDate(3, user.getBirth());
stat.setString(4, user.getName());
int i = stat.executeUpdate();
return i;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DataAccess.closeConnection(conn, stat);
}
return -1;
}
出现错误的Test类的代码
public class Test {
public static void main(String[] args) throws InterruptedException {
UserImpl impl = new UserImpl();
//查询所有数据
List<User> list = impl.findAllUser();
for(User i : list) {
System.out.println(i.toString());
}
System.out.println();
//更新数据
List<User> list1 = impl.findAllUser();
for(User i : list1) {
System.out.println(i.toString());
}
}
}
出现错误的位置及原因
当运行完第一个查询的时候(运行完以下代码之后)
//查询所有数据
List<User> list = impl.findAllUser();
for(User i : list) {
System.out.println(i.toString());
}
数据库连接被断开,conn.close(); 但是关闭连接之后 conn不为空,导致运行到第二个查询的时候(运行到以下代码的时候)
//更新数据
List<User> list1 = impl.findAllUser();
for(User i : list1) {
System.out.println(i.toString());
}
导致了连接数据库失败,因为在连接数据库的时候,前提为
if(conn == null) {
所以出现了错误
假如去掉上面这个条件之后,是可以进行连续两次查询的
询问老师的结果
问了老师这个错误怎么处理之后,老师先给我来一句:你为啥要这么测试方法?我回答说因为想着“查询之后更改数据,然后再查询,能够直观的对比”。老师说:没有这种测试的方法的,这个错误不是代码的问题而是你根本不需要这样测试。
解决的方法(不知道能不能在项目中用)
- 将在连接数据库时的 if(conn == null) 条件去掉,使之无论为不为空都重新连接(导致的后果:可能上一个连接还未关闭就重新连接)
- 将两次查询重新封装作为一个功能,只连接一次数据库就能完成其所需要的功能。
总结
多思考,多测试,多发现,多理解。
本文仅作记录,如果上述有错,请指出,不胜感激!