2016-11-02 18 views
0

JSONデータを受け入れて返すRESTサーバーで作業しています。特定の入力値(入力JSONから)の場合、Hibernate(Springと統合)はデータベースにクエリを行い、JSONをRest Controllerに返します。クライアントアプリケーションは、応答を読み取るために、変更できないタイムアウトが5秒になるように設計されています。応答時間が長いHibernate query.list()

この問題は、(常にそうとは限りませんが)Hibernateが指定された制限時間内にデータを処理できないため、クライアント側でタイムアウトエラーが発生することがあります。

私は、ネット上の他の投稿で、Beanクラスで完全なコンストラクタを使用し、遅延読み込みを行うことを確認しました。私の場合はどちらも当てはまります。以下は、この問題を引き起こすDAOImplメソッドの1つです。ここでは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(); 
} 

正しい方法で実装しているかどうか教えてください。

EDIT:

@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(); 
} 

答えて

0

私はどうしたらまず最初に行われたすべての変更と同様の問題を引き起こして別の方法を投稿すること(see here)生成されたSQLクエリをログに記録することです。あなたがそれらを持っていれば、あなたはもっと掘り下げをすることができます:

  • 本当にデータベース自体は問題ではありませんか?不正なテーブルおよび/または結合インデックスは一般的な原因です。
    • 手動でデータベース
  • に対して実行したときに生成されたSQLクエリがうまく機能しないかどうかを確認するために、各クエリ
  • チェックを行う際の開始時刻と終了時刻を記録しますgetOfferOnRuleNameBalance
  • の開始時刻と終了時刻を記録します
  • 休止状態のマッピングとコードがN + 1選択を引き起こしていますか?遅延ロードされたコレクション内の各項目に対して複数のSELECT文が生成されているかどうかがわかります。これはループのどこかで発生する可能性があります。または、遅延ロードされたコレクションにアクセスして、その中の各要素をチェックする方法によって、equals()toString()、またはhashCode()が発生する可能性があります。

それぞれのクエリを記録することで、問題の原因となっているのか、それとも両方のクエリであるのかがわかります。

さらにトラブルシューティングを行うには、休止状態のオブジェクト自体のマッピングを参照する必要がありますが、これは少なくとも始点を与えるかもしれません。

+0

私はあなたが示唆したように試み、そのquery.list()が原因であることが判明しました。 query.list()の直前のロガーは動作しましたが、次のロガーは印刷されませんでした。 SQlを手動で実行すると、秒単位でデータが返されました。すべてのデータ操作ロジックはDAOImplメソッドで記述されているため、別の場所にループはありません。したがって、コードで言及されているSQLクエリに対応するテーブルは子テーブルであるため、これらのマッピング関連の問題は表示されません。さらに驚くべきことに、メソッドは同じ入力に対してデータを返しますが、アプリケーションをブラウズしているときに後で呼び出されると失敗します。他の情報が必要な場合はお知らせください。 –

+0

さらに、条件を使用してすべてのクエリを変換しました。 selectクエリの場合でもsession.close()の直前にコミットされたトランザクション。また、セッションを使用して単一のクエリを起動する個別のメソッドを修正しました。問題は神経に乗っている。 –

関連する問題