【问题标题】:how to store data retrieved from database into a variable so that I can avoid hitting database again如何将从数据库检索到的数据存储到变量中,这样我就可以避免再次访问数据库
【发布时间】:2017-02-26 05:45:00
【问题描述】:

我有一个 web 应用程序,我需要通过 JDBC 从数据库中检索数据并将其显示在前端。它是静态数据,不会更改。所以我只需要检索一次数据并将其存储在一个静态变量中,这样我就可以每次都使用该数据而不是查询数据库。下面是示例代码:

 public class SampleClass(){
    static Map<String, BigDecimal> productMap = null;

    public Map<String, BigDecimal> getDatafromDB(Connection conn, PreparedStatement stmt, ResultSet rs) throws SQLException{

        if(productMap == null){

          productMap = getProductID(conn, stmt, rs);
        }

        return productMap;
        }

public Map<String, BigDecimal> getProductID(Connection conn, PreparedStatement stmt, ResultSet rs) throws SQLException {

        logger.debug("retrieving product ID's from product table..");
        Map<String, BigDecimal> productMap = new HashMap<String, BigDecimal>();
        stmt = conn.prepareStatement("Select * from PRODUCTTABLE");
        rs = stmt.executeQuery();
        logger.debug("Product ID's retrieved");
        while(rs.next()){

            productMap.put(rs.getString("PRODUCT_NAME"),rs.getBigDecimal("PRODUCT_ID"));
        }

        if (stmt != null) {
            stmt.close();
        }
        if (rs != null) {
            rs.close();
        }

        return productMap;
    }

    }

我通过 http servlet 请求从 UI 调用此方法。当我第一次运行它时,由于地图为空,它会查询数据库并获取数据并将其发送到 UI。当我第二次使用新请求再次点击 servlet 时,产品映射为空,并且再次查询数据库并获取数据。由于它是一个静态变量,它应该只初始化一次 rite 那么为什么它对于第二个请求仍然为空。有人可以更正我的代码吗?

提前致谢

【问题讨论】:

  • 你需要告诉我们retreivedatafromDB()方法
  • 如果其他人在您的方法调用之间更新数据库怎么办?缓存一些数据库数据真的没有意义
  • 缓存是一种您可能必须使用的技术,如果您想填充您的静态映射,还可以考虑使用静态初始化器!该类应该只加载一次!
  • 产品表不会被其他人更新,因为它是一个主表,并且只有在推出新产品时才会对该表进行更改。对于在 UI 中提交的每个申请表,我们需要从数据库中检索产品并与用户提交的产品进行比较,并将相关的产品 ID 存储在不同的表中。为此,我需要在前端提交申请表时随时访问数据库并获取产品。因此,由于数据是静态的,即预加载到 DB 中,如何避免多次访问 DB?
  • 另外,当我们向数据库添加新产品时,我们将停止服务器并更新数据库,然后我们将重新启动应用服务器。我不确定这是否是一个好方法

标签: java jdbc static static-methods


【解决方案1】:

问题的根本原因是 servlet 是无记忆的。所以静态变量无济于事。您需要的是一个会话属性。

我建议将您的变量添加为会话属性。首先,您需要创建一个实现 Serializable 的封装类:

public class SampleResult implements Serializable {

    private Map<String, String> productMap;

    public void setProductMap(Map<String, String> productMap) {
        this.productMap = productMap;
    }

    public Map<String, String> getProductMap() {
        return productMap;
    }
}

现在在您的 servlet 中:

HttpSesssion session = request.getSession();

Map<String, String> productMap;
SampleResult result;

if (session.getAttribute("productMap") == null) {
    productMap = retrievedatafromDB();
    result = new SampleResult();
    sampleResult.setProductMap(productMap);
    session.setAttribute("productMap", result);// session attribute created
} else {
    result = session.getAttribute("productMap");// retrieve session attribute
    productMap = result.getProductMap();
}

【讨论】:

  • 这仅在该产品图是针对特定用户/会话的情况下才有用。我的猜测是 OP 希望该产品图成为应用程序范围,而不是会话。
  • 感谢您的建议,但正如 Mark 所说,我希望产品图是应用范围而不是会话范围。
猜你喜欢
  • 2020-06-14
  • 2011-08-16
  • 1970-01-01
  • 1970-01-01
  • 2017-06-19
  • 2016-10-13
  • 2014-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多