java - SQL 准备语句;我做对了吗?

标签 java sql sql-server jdbc prepared-statement

我正在构建一个 Web 应用程序,在静态类和数据库之间使用单个(非池化)全职 (jdbc) 连接。预计这将是一个低流量站点,并且静态方法是同步的。为了加快对产品信息的访问速度,我第一次尝试PreparedStatements。当我在本地主机上进行测试时,确保我是唯一运行该应用程序的人。对我来说,很明显我的准备好的语句比我在该过程早期使用的未准备的语句慢。这可能不是一个公平的比较。未准备好的语句从一个表中获取单个结果集,然后就完成了。正如您从下面的代码中看到的,我对准备好的语句所做的涉及三个表和多个查询。但由于这是我第一次,我希望得到评论和评论。这确实有效;即所有数据均按预期检索。

下面的第一个方法 (initialize()) 在应用程序首次启动时从 servlet init() 方法调用一次。第二种方法 (getItemBatch()) 检索与产品名​​称 (Titel) 匹配的尽可能多的产品项的信息。我的小型开发/测试数据库包含不到 100 个(总计)项目,并且只有 1-3 个项目与每个名称匹配;最常见的是 1。服务器应用程序和数据库位于同一台计算机上,我通过本地主机从浏览器进行访问。与获取上面提到的主产品列表(所有项目)相比,对这些详细产品数据的持续明显等待令我感到惊讶。

  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。我们的想法是创建它们一次(并且仅一次),并让它们永远可供所有用户使用(即直到应用程序或服务器关闭)。我想要一种伪存储过程。我会直接使用存储过程,但数据库的存在是为了支持另一个应用程序(他们的内部销售系统),并且我将使用它进行只读互联网销售......避免与他们的维护工作发生任何潜在的冲突或协议(protocol)等,不做任何改变他们的数据库设置。我建议我的应用程序使用仅限只读权限的新帐户。想想看,我还没有测试是否可以在该模式下使用准备好的语句;看起来应该可行。

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

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

最佳答案

如果您创建 Web 应用程序并使用 Tomcat、jetty 等 Web 容器,您始终可以使用 jdbc 数据源和连接池。很简单。很好的解释给出了 here

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

关于java - SQL 准备语句;我做对了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14535482/

相关文章:

java - 使用 Serial Java 从传入数据中检测 <CR>

java - 正则表达式模式匹配

java - 如何在 Java 中解码 XHTML 和/或 HTML5 实体?

sql - 从三个表中选择数据?

python - 当参数有时可以为NULL时如何参数化SQL查询?

c# - Asp.Net,SQL和TimeZones

java - 选择后的 Spring MVC 细化下拉列表

sql - 在 SQL 中使用累积需求时在聚合级别上优化表概览

sql - 过滤具有相同 ID 的前一行具有特定值的数据

不支持 SQL Server 版本 10 错误