【问题标题】:Hibernate is not responding while querying查询时休眠没有响应
【发布时间】:2018-07-23 08:02:40
【问题描述】:

Hibernate 查询返回结果时间过长如何处理。我已经配置了查询超时,但是在调试时它显示数据库正在通过返回数据来响应,但是休眠无法映射给定的数据。

我不希望这种情况在生产中发生,因为我的查询可能会因为休眠没有响应而失败。

我需要一个解决方案来摆脱这种情况。

setProperty("javax.persistence.query.timeout", 180000);

JPAQuery query = queryFactory.select(....)
do{
   List<Tuple> data = query.fetch().limit(5000);
   //--------
} while(flag)

上面的代码适用于较小的数据,但对于某些数据集/条件,数据很大,最终休眠没有响应。

【问题讨论】:

  • 我们需要更多信息,例如您的一些代码、您如何构建查询、pojo 是如何、您如何将查询结果包装到您的类中等等
  • 查询超出普通 querydsl,并通过休眠 DAO 存储库查询。数据库中有 130 列,其中 2 列包含大量数据。我们将其导出到 csv 文件。
  • 基本上我希望休眠自动终止请求,如果它花费的时间太长

标签: java postgresql hibernate querydsl


【解决方案1】:

如果

  • 使用 Lazy Fetching 而不是像 @ManyToMany(mappedBy="authors", fetch=FetchType.LAZY) 这样的 Eager Fetching

  • 或者可以检查是否有这些Mistakes

  • 您正在使用 HibernateDaoSupport.getSession(),但从未使用 releaseSession() 返回它们(如 javadocs 中所述)。

a) 使用HibernateDaoSupport.getHibernateTemplate() 干净地创建/销毁会话 b) 在 finally 块中使用 getSession()/releaseSession() c) 忘记HibernateDaoSupport,定义事务并使用sessionFactory.getCurrentSession()

  • 使用,session.refresh(entity) or entityManager.refresh(entity)(如果您使用 JPA)将为您提供来自 DB 的最新数据。

【讨论】:

    【解决方案2】:
    1) For setting the timeout in Hibernate query you can set hint "javax.persistence.query.timeout"
    
    
    Code snippet ::
    
    List<Test> test= em.createQuery("SELECT * FROM Test t")
        .setHint("javax.persistence.query.timeout", 1)
        .getResultList();
    
    2) In case 2 columns are containing large data ,you can use CLOB and BLOB types for huge dataset.
    

    【讨论】:

    • javax.persistence.query.timeout 已经处理好了,但是由于我猜数据获取大小更多,所以映射部分需要时间。
    • 只有在给定的提取大小没有响应时,我才能动态减小提取大小
    • 这两列的数据类型是什么?
    • postgres 中的文本
    【解决方案3】:

    根据您的上一条评论,您正在寻找一种方法来管理某些查询的超时。

    您可以在使用 Hibernate 创建 org.hibernate.Query 时实现此目的:

    Query queryObject = //initialize your query as you need;
    queryObject.setTimeout(10); //that int represents the seconds of timeouts.
    

    希望对你有帮助

    【讨论】:

    • 我在休眠配置中设置了相同的设置,但它似乎不起作用,因为查询返回结果但休眠没有。
    • 设置超时 - 尽管我已将其设置在休眠级别,但我无法直接在 JPAQuery 上找到该实现
    • 这就是我在第一条评论中询问更多细节的原因:如果您没有在问题中添加一些代码,我们可以假设您在做什么:)
    • 我添加了一段非常基本的代码来说明我正在处理的事情
    【解决方案4】:

    最后我找不到任何直接的方法来控制休眠查询调用。 超时对我不起作用,因为 Postgres 已经返回了结果集,但是由于数据大小,hibernate 需要时间进行映射(如果我错了,请纠正我)。

    下面的一段代码救了我。

    ExecutorService executor = Executors.newSingleThreadExecutor();
    List<Future<List<Tuple>>> futureData = executor.invokeAll(Arrays.asList(new QueryService(params...)), 2, TimeUnit.MINUTES);
    executor.shutdown();
    for (Future future : futureData) {
        try {
             data = (List<Tuple>) future.get();
             } catch (CancellationException e) {
                     if (EXPORT_LIMIT > 1000) {
                                EXPORT_LIMIT = 1000;
                            } else if (EXPORT_LIMIT > 500) {
                                EXPORT_LIMIT = 500;
                            } else if (EXPORT_LIMIT > 100) {
                                EXPORT_LIMIT = 100;
                            } else {
                                throw e;
                            }
                            isValid = false;
                            break;
                        }
                    }
    

    所以基本上我的默认获取限制为 5000,如果不工作,那么我会一直尝试到 100。 如果 100 的 fetch size 也失败,则会抛出异常。

    谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-29
      • 2011-08-09
      • 1970-01-01
      • 2013-11-07
      相关资源
      最近更新 更多