Is it possible to set configurable timeout to Mybatis mapper?

44 Views Asked by At

Is it somehow possible to set configurable timeout to mybatis mapper?

This works:

<select id="getData" resultType="Data" resultMap="dataMap" timeout="1"><![CDATA[
        SELECT * from tab;
    ]]></select>

But I need to have the timeout configurable, something like

<select id="getData" resultType="Data" resultMap="dataMap" timeout="#{timeout}"><![CDATA[
        SELECT * from tab;
    ]]></select>

Or do I have to implement JDBC prepared statement and set the timeout there?

PreparedStatement stm;
stm.setQueryTimeout(timeOut);
1

There are 1 best solutions below

0
ave On

A possible solution is to use a plugin (a.k.a. interceptor).

import java.sql.Statement;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;

@Intercepts(@Signature(type = StatementHandler.class,
  method = "parameterize", args = { Statement.class }))
public class SetQueryTimeoutInterceptor implements Interceptor {
  @Override
  public Object intercept(Invocation invocation) throws Throwable {
    Statement statement = (Statement) invocation.getArgs()[0];
    Integer timeout = QueryTimeoutValue.get();
    if (timeout != null) {
      statement.setQueryTimeout(timeout);
    }
    return invocation.proceed();
  }
}

QueryTimeoutValue is a class that holds a ThreadLocal.

public class QueryTimeoutValue {
  private static ThreadLocal<Integer> value = new ThreadLocal<>();

  public static void setTimeout(Integer timeout) {
    value.set(timeout);
  }

  public static Integer getTimeout() {
    return value.get();
  }
}

You can set the timeout value before executing the target statement.

QueryTimeoutValue.set(60);
X x = mapper.getData();