【问题标题】:Hibernate query.list() taking long time to respondHibernate query.list() 需要很长时间才能响应
【发布时间】:2017-03-16 05:35:30
【问题描述】:

我正在开发一个接受并返回 JSON 数据的 REST 服务器。对于特定的输入值(来自输入 JSON),Hibernate(与 Spring 集成)查询数据库并将 JSON 发送回 Rest Controller。客户端应用程序被设计为具有 5 秒的超时时间,用于读取响应,该响应不可更改。

现在的问题是有时(并非总是但大多数情况下)Hibernate 无法在给定的时间限制内处理数据,因此在客户端收到超时错误。

我检查了网络上的其他帖子,以在 bean 类中使用完整的构造函数并进行延迟加载。就我而言,两者都是正确的。下面是导致此问题的 DAOImpl 方法之一。在这里我要查询 2 个表(数据不多,每个表中大约 20 个条目),将所有数据添加到 json 数组并发回。

@Override
   public String getOfferOnRuleNameBalance(String inputJsonString) {
    JSONObject saveJsonObject = new JSONObject(inputJsonString);
    String ruleName    =   saveJsonObject.getString("rulename");
    int currentAccountBalance    =   saveJsonObject.getInt("currentAccountBalance");
    Session session1 = getSession();
    Criteria criteria =session1.createCriteria(PaymentPlanOffers.class);
    criteria.add(Restrictions.eq("rulename", ruleName));
    @SuppressWarnings("unchecked")
    List<PaymentPlanOffers> offerList=criteria.list();
    JSONArray jsonArray = new JSONArray();
    for(PaymentPlanOffers object:offerList)
    {
        JSONObject jsonObject1 =new JSONObject();
        jsonObject1.put("instAmount",object.getAmountPercent());
        jsonObject1.put("instNumber", object.getNumInstallment());
        jsonObject1.put("frequency", object.getFrequency());
        jsonObject1.put("offerId", object.getId());
        jsonObject1.put("offerName", object.getOfferName());
        jsonObject1.put("active", object.isActive());
        jsonObject1.put("accepted", object.isAccepted());
        jsonObject1.put("totalAmount", currentAccountBalance);
        jsonObject1.put("startDate", object.getStartDate());
        jsonObject1.put("endDate", object.getEndDate());
        jsonArray.put(jsonObject1);
    }

    Criteria criteria2 =session1.createCriteria(CustomPlanOffer.class);
    criteria2.add(Restrictions.eq("rulename", ruleName));
    @SuppressWarnings("unchecked")
    List<CustomPlanOffer> customOfferList=criteria2.list();
    for(CustomPlanOffer object:customOfferList)
    {
        JSONObject jsonObject1 =new JSONObject();
        jsonObject1.put("instAmount", object.getAvgInstallment());
        jsonObject1.put("instNumber", object.getNumOfInstallment());
        jsonObject1.put("frequency", object.getFrequency());
        jsonObject1.put("offerId", object.getId());
        jsonObject1.put("offerName", object.getName());
        jsonObject1.put("active", object.isActive());
        jsonObject1.put("accepted", object.isAccepted());
        jsonObject1.put("totalAmount", object.getTotalPaymentAmount());
        jsonObject1.put("startDate", object.getStartDate());
        jsonObject1.put("endDate", object.getEndDate());
        jsonArray.put(jsonObject1);
    }

    JSONObject mainObj = new JSONObject();
    mainObj.put("allOffers", jsonArray);
    session1.close();
    return mainObj.toString();
}

如果我以正确的方式实施它,请告诉我。

编辑:发布另一种导致所有修改完成的类似问题的方法

@Override
public String getAllOffers(String inputJsonString) {
    Session session = getSession();
    Transaction t = session.beginTransaction();
    String hql = "FROM PaymentPlanOffers";
    Query query = session.createQuery(hql);
    @SuppressWarnings("unchecked")

    List<PaymentPlanOffers> results = query.list(); //this is where it goes on hang


    JSONArray jsonArray = new JSONArray();
    for(PaymentPlanOffers object:results)
    {
        JSONObject jsonObject1 =new JSONObject();
        jsonObject1.put("offername", object.getOfferName());
        jsonObject1.put("rulename", object.getRulename());
        jsonObject1.put("id", object.getId());
        jsonObject1.put("offerMessage", object.getOfferMessage());
        jsonArray.put(jsonObject1);
    }
    JSONObject mainObj = new JSONObject();
    mainObj.put("allOffers", jsonArray);
    t.commit();
    session.close();
    return mainObj.toString();
}

【问题讨论】:

    标签: java mysql json spring hibernate


    【解决方案1】:

    我要做的第一件事是记录正在生成的 SQL 查询 (see here)。拥有它们后,您可以进行更多挖掘:

    • 您确定不是数据库本身的问题吗?错误的表和/或连接索引是常见原因。
      • 记录getOfferOnRuleNameBalance的开始和结束时间
      • 记录每次查询的开始和结束时间
      • 检查生成的 SQL 查询在手动运行数据库时是否性能不佳
    • 您的休眠映射和代码是否会导致 N+1 选择?您将知道是否为延迟加载集合中的每个项目生成了多个 SELECT 语句。这也可能是由某个地方的循环引起的,或者是由 equals()toString()hashCode() 方法访问延迟加载的集合并检查其中的每个元素引起的。

    记录每个查询还会告诉您是只有一个查询导致了问题,还是两个查询都有。

    要进行更多故障排除,我必须查看休眠对象本身的映射,但这至少可以为您提供一个起点。

    【讨论】:

    • 我按照您的建议进行了尝试,发现它的 query.list() 是罪魁祸首。 query.list() 之前的记录器工作但下一个记录器没有打印。在手动运行 SQl 时,会在部分秒内返回数据。所有数据操作逻辑都用 DAOImpl 方法编写,因此其他地方没有循环。由于与代码中提到的 sql 查询对应的表是子表,因此我看不到与这些映射相关的问题。更令人惊讶的是,该方法有时会为相同的输入返回数据,但在浏览应用程序时稍后调用时会失败。如果需要其他信息,请告诉我。
    • 我进一步使用条件转换了所有查询。在 session.close() 之前提交事务,即使是选择查询。并修改了单个方法以使用会话触发单个查询。问题让人紧张。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 1970-01-01
    相关资源
    最近更新 更多