【问题标题】:What could be the possibilities of using a thread-unsafe java.sql.Connection object in java?在 java 中使用线程不安全的 java.sql.Connection 对象的可能性是什么?
【发布时间】:2010-11-18 17:45:07
【问题描述】:

我正在处理一个遗留代码,其中单例 dao 类中的连接对象是一个成员变量,并且容易出现竞争条件。

我知道这是一个潜在的设计问题,但是我有兴趣了解在处理 java 中的 jdbc 连接对象时可能会想到的不同类型的问题。

以下是EventLoggerDAO类代码:

package com.code.ref.dao;

 import java.sql.Connection;
 import java.sql.PreparedStatement;

 import com.code.ref.utils.common.DBUtil;
 import com.code.ref.utils.common.PCMLLogger;

 public class EventLoggerDAO {

 private static EventLoggerDAO staticobj_EventLoggerDAO;

 private Connection obj_ClsConnection;

 private PreparedStatement obj_ClsPreparedStmt;

 private EventLoggerDAO() {
  try {
   obj_ClsConnection = DBUtil.getConnection();
  } catch (Exception e) {
   PCMLLogger.logMessage(EventLoggerDAO.class, "EventLoggerDAO()", "Some problem in creating db connection:" + e);
  }
 }

 public static synchronized EventLoggerDAO getInstance() {
  if (staticobj_EventLoggerDAO == null) {
   synchronized (EventLoggerDAO.class) {
    if (staticobj_EventLoggerDAO == null)
     staticobj_EventLoggerDAO = new EventLoggerDAO();
   }
  }
  return staticobj_EventLoggerDAO;
 }

 public void addEvent(String sName, String sType, String sAction, String sModifiedBy) throws Exception {
  StringBuffer sbQuery = new StringBuffer();
  sbQuery.append("INSERT INTO TM_EVENT_LOG (NAME, TYPE, ACTION, MODIFIED_BY) ").append("VALUES (?, ?, ?, ?) ");
  if(obj_ClsConnection == null)
   obj_ClsConnection = DBUtil.getConnection();

  obj_ClsPreparedStmt = obj_ClsConnection.prepareStatement(sbQuery.toString());
  obj_ClsPreparedStmt.setString(1, sName);
  obj_ClsPreparedStmt.setString(2, sType);
  obj_ClsPreparedStmt.setString(3, sAction);
  obj_ClsPreparedStmt.setString(4, sModifiedBy);
  obj_ClsPreparedStmt.executeUpdate();
  if (obj_ClsPreparedStmt != null) {
   obj_ClsPreparedStmt.close();
   obj_ClsPreparedStmt = null;
   }
  }
 }

发现问题

有时会发生表TM_EVENT_LOG停止插入,服务器日志中甚至没有异常。

我怀疑在竞争条件下,不同线程持有的连接对象可能会导致状态不一致,也可能不会提交数据。连接是通过维护连接池的 websphere 数据源派生的。

有什么想法或想法为什么会发生这种情况?

【问题讨论】:

  • 感谢 Carl 格式化代码。我最初尝试过,但徒劳无功。
  • 这里的竞争条件存在明显且非常严重的问题。我建议解决您知道的问题,而不是试图弄清楚它们是如何/是否导致观察到的症状。 (奥卡姆剃刀等等)。
  • 我从应用服务器日志中观察到的是上面的代码有“java.sql.SQLException: ORA-01000: maximum open cursors exceeded”。每次运行 sql 语句后是否都必须关闭连接,即使在我最疯狂的想法中我希望这个对象保持这个连接而不将它返回到连接池?

标签: java database multithreading jdbc database-connection


【解决方案1】:

一切都可以在这里发生。请注意,obj_ClsPreparedStmt 是成员变量,而它被用作局部变量 - 这似乎是比共享 Connection 更严重的问题。

【讨论】:

  • 我知道上面的代码是一个严重的错误,但我更想知道的是,即使连接处于自动提交状态,插入如何可能在此表上停止?
  • 它甚至可能与连接无关。看代码——一个线程可以覆盖obj_ClsPreparedStmt,而另一个线程正在设置参数。
  • 同意,但即便如此,也必须在preparedStatement 对象上触发executeUpdate()。因此,即使有损坏的值,也应该已经观察到插入完全停止,直到下一次应用程序服务器重新启动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
  • 2021-07-15
  • 2012-03-14
相关资源
最近更新 更多