Hibernate在查询时没有响应

时间:2018-07-23 08:02:40

标签: java postgresql hibernate querydsl

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

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

在这种情况下,我需要一个解决方案。

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

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

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

4 个答案:

答案 0 :(得分:1)

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.

答案 1 :(得分:0)

尝试执行以下步骤,如果

  • 使用惰性获取而不是像@ManyToMany(mappedBy="authors", fetch=FetchType.LAZY)

  • 或者可以检查是否有任何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 :(得分:0)

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

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

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

希望这会有所帮助

答案 3 :(得分:0)

最后,我找不到任何直接方式来控制休眠查询调用。 超时对我来说不起作用,因为Postgres已经返回了结果集,但是由于数据大小,休眠状态在映射上花了一些时间(如果我错了,请纠正我)。

下面的代码救了我。

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的提取大小也失败,则会引发异常。

谢谢。