0

我正在构建一个 Web 应用程序,在静态类和数据库之间有一个(非池)全时(jdbc)连接。预计这是一个低流量站点,并且静态方法是同步的。为了加快对产品信息的访问,我第一次尝试 PreparedStatements。当我在 localhost 上进行测试时,确保我是唯一一个运行该应用程序的人。我似乎很清楚,我准备好的语句比我在此过程中早些时候使用的未准备好的语句要慢。这可能不是一个公平的比较。未准备好的语句从一个表中得到一个结果集,然后就完成了。从下面的代码可以看出,我对准备好的语句所做的事情涉及三个表和多个查询。但由于这是我第一次,我会很感激评论和评论。这确实有效;IE

下面的第一个方法 (initialize()) 在应用程序首次启动时从 servlet init() 方法调用一次。第二种方法 (getItemBatch()) 检索有关与产品名称 (Titel) 匹配的尽可能多的产品项目的信息。我的小开发/测试数据库只有不到 100 个(总计)项目,每个名称只有 1-3 个项目匹配;大多数情况下只有 1. 服务器应用程序和数据库在同一台机器上,我通过 localhost 从浏览器访问。与获取上述主产品列表(所有项目)相比,我对持续可感知的等待详细产品数据感到惊讶。

  public static boolean initialize (Connection connArg, String dbNameArg, String dbmsArg) {

    con = connArg;
    dbName = dbNameArg;
    dbms = dbmsArg;
    sqlserver_con = connArg;

    ItemBatchStatement =
          "select Cartnr, Hgrupp, Prisgrupp, Moms from dbo.Centralartregister " +
           "where Titel = ?";

    ForArtNrStatement =
          "select Artnr, Antal from dbo.Artikelregister " +
           "where Cartnr = ? and Antal > 0";

    ItemHgruppStatement =
            "select Namn from dbo.Huvudgrupper " +
             "where Hgrupp = ?";

    try {
      con.setAutoCommit(false);
      getItemBatch = con.prepareStatement(ItemBatchStatement);
      getForArtNr = con.prepareStatement(ForArtNrStatement);
      getItemHgrupp = con.prepareStatement(ItemHgruppStatement);
    } catch (SQLException e) {
      return(false);
    } finally {
      try {con.setAutoCommit(true);} catch (SQLException e) {}
    }
    return(true);
  }

-

  public static synchronized String getItemBatch (String Titel) throws SQLException {

    String ret_xml;
    ResultSet rs  = null;
    ResultSet rs1 = null;
    ResultSet rs2 = null;

    Titel = charChange(Titel);
    ret_xml = "<ItemBatch Titel='" + Titel + "'>";
    try {
      con.setAutoCommit(false);
      getItemBatch.setString(1,Titel);
      rs = getItemBatch.executeQuery();
      while (rs.next()) {
        getForArtNr.setInt(1,rs.getInt("Cartnr"));
        rs1 = getForArtNr.executeQuery();
        getItemHgrupp.setInt(1,rs.getInt("Hgrupp"));
        rs2 = getItemHgrupp.executeQuery();
        if (rs1.next() && rs2.next()) {
          ret_xml += "<item><Hgrupp>" + rs2.getString("Namn") + "</Hgrupp><Price>" + rs.getInt("Prisgrupp") + "</Price><Moms>" + rs.getInt("Moms") + "</Moms><Cartnr>" + rs.getInt("Cartnr") + "</Cartnr><Artnr>" + rs1.getInt("Artnr") + "</Artnr></item>";
        }
      }
      ret_xml += "</ItemBatch>";
      return(ret_xml);
    } catch (SQLException e) {
      return("SQLException: " + e);
    } finally {
      try {con.setAutoCommit(true);} catch (SQLException e) {}
      if (rs != null) {rs.close();}
      if (rs1 != null) {rs1.close();}
      if (rs2 != null) {rs2.close();}
    }
  }

.

更新:我仍在谷歌搜索并寻找做得更好的方法。让我补充一点供您考虑。

我正在通过 servlet 的 destroy() 方法关闭准备好的语句;调用上述方法“initialize()”以创建它们的同一个 servlet。我们的想法是创建一次(并且只有一次)并让所有用户永远都可以使用它们(即直到应用程序或服务器关闭)。我要找一种伪存储过程。我会直接使用存储过程,但是数据库的存在是为了支持另一个应用程序(他们的内部销售系统),我打算将它用于互联网销售只读...避免与他们的维护工作产生任何潜在冲突或协议等,不做任何事情来改变他们的数据库设置。我建议我的应用程序使用限制为只读权限的新帐户。想想看,我没有 t 测试我是否可以在该模式下使用 Prepared Statements;似乎它应该工作。

每个结果集都在创建它们的方法的 finally 块中关闭。我想这样可以吗?我为多个结果集(在后两个)重复使用相同的 RS 变量名称,但只关闭一次。可是等等!我什至需要那个吗?ResultSet 在方法的范围内声明。如果在不关闭旧的情况下重置它们不会导致泄漏,那么退出该方法应该也可以自行完成。它是一种静态方法,但每次使用时都会重置 ResultSets(至少)。因此,最多只有一组 ResultSet 句柄可供重用;不失控“泄漏”。

我想知道我是否可以同时在循环中发送两个选择请求,只需将它们变成一个用';'分隔的准备好的语句。或者刚刚发现“MultipleActiveResultSets=True”;允许 SQL Server 在单个连接上处理多个事务请求的文档……仍在调查此问题。或者有没有另一种方法来创建一个准备好的语句,通过一次提交来获取所有数据?(在我看来,往返次数太多了。)最后,我可能会从使用连接池中得到提升,但我还没有这样做。现在在我的项目中这是低优先级,但我可能必须在我们上线之前完成它。

4

1 回答 1

1

如果你创建 web 应用程序并使用一些 web 容器,如 tomcat、jetty 等,你总是可以使用 jdbc 数据源和连接池。很简单。很好的解释在这里

如果您不想使用连接池,我想最好使用上面链接中描述的方法范围连接

于 2013-01-26T09:32:42.603 回答