如何在Hibernate上将查询超时设置为少于1秒?

时间:2019-07-18 12:26:05

标签: java hibernate jpa timeout

我使用Hibernate 5.4.1.Final和Java8。我通过

将查询超时设置为TypedQuery。
typedQuery.setHint("javax.persistence.query.timeout", 400);

但是休眠状态将其转换为秒,并四舍五入为0。当我得到提示时

typedQuery.getHints();
{org.hibernate.timeout=0, javax.persistence.query.timeout=0}

如果我将某项设置为500以上,则舍入为1秒。

typedQuery.setHint("javax.persistence.query.timeout", 500);
typedQuery.getHints();
{org.hibernate.timeout=1, javax.persistence.query.timeout=1000}

如何设置以毫秒为单位且小于1秒的查询超时?

谢谢。

4 个答案:

答案 0 :(得分:1)

Hibernate不会自行处理此超时,而是通过JDBC Statement.setTimeout方法将其提供给JDBC驱动程序。 (请参阅:https://thoughts-on-java.org/11-jpa-hibernate-query-hints-every-developer-know/

也请参见此问题https://bugs.eclipse.org/bugs/show_bug.cgi?id=456067

似乎每当JDBC驱动程序仅为此配置指定秒数时,Hibernate可能就被迫将此值转换为秒数。请检查JDBC驱动程序提供的超时准确性。这很可能是预期的行为。

如果无论如何以秒为单位指定,网络超时似乎更合适,因为随机网络延迟很难避免。

答案 1 :(得分:0)

我们通过设置Postgresql DB的 statement_timeout 参数找到了一种解决方法。当需要限制查询执行时间时,我们执行以下脚本。确保超时值是可配置的。运行查询后,我们将此参数设置为0。

Session session = entityManager.unwrap(Session.class);
session.doWork(new Work() {

    @Override
    public void execute(Connection connection) throws SQLException {
        connection.createStatement().execute("set statement_timeout = 300");
    }
});

答案 2 :(得分:0)

在调试(很多)休眠和我的(maria-db)JDBC连接器之后,我遇到了完全相同的问题。

我注意到下面的代码行(在休眠内核中),这基本上迫使您使用MS格式的秒数(例如1000)作为提示“ javax.persistence.query.timeout”,否则,它将将舍入该值(值是提示的值)

这基本上意味着您不能有1-999毫秒,而只能是0或1秒

int timeout = (int)Math.round( ConfigurationHelper.getInteger( value ).doubleValue() / 1000.0 );

Code line was taken from this source code

我希望您能找到解决方案,因为我找不到解决方法

编辑:

我能做到这一点的唯一方法是使用连接的网络超时。

请注意,由于此操作是“手动” 完成的,因此不会像冬眠(关闭/释放资源)那样为您进行清理(也不会调用KILL命令)自行完成

int timeoutMs = 250;
var connection = jdbcTemplate.getDataSource().getConnection();
connection.setNetworkTimeout(Runnable::run, timeoutMs);
var callableStatement = connection.prepareCall("{call testSp()}");
// Setup your SP parameters
callableStatement.execute();

答案 3 :(得分:-2)

尝试一下:

typedQuery.setHint("org.hibernate.timeout", "1");
typedQuery.getSingleResult();