0

(我在 Teradata v12 上使用 MyBatis v3、Java SE v6、Tomcat v6 和 Spring v3。)

我当前项目的技术要求之一是使用 Teradata 中的查询分段功能。这是通过在需要时运行如下语句来完成的:

SET QUERY_BAND='someKey=someValue;' FOR TRANSACTION;

我想为我的所有电话设置一个查询带。但是,我不确定如何以干净且可重用的方式添加此功能,而不必将其添加到<select>映射器文件中的每个语句中,如下所示:

<sql id="queryBand"> 
    SET QUERY_BAND='k=v;' FOR TRANSACTION; 
</sql>

<select ...> 
   <include refid="queryBand"/> 
   ... some SQL performing a SELECT 
</select>

我对上述问题的看法是:1)查询带的格式在我的所有映射器 XML 文件中都是相同的,除了 k 和 v,我想在每个<select>(等)的基础上进行自定义。我不确定如何在不必传入 k 和 v 值的情况下进行此自定义,这会使我的映射器界面变得混乱。2)上面的代码中有重复让我感到不安。开发人员必须记住包含 queryBand SQL,有些人会在某个阶段忘记它(墨菲定律)。

有人可以指出我以更清洁的方式实现查询绑定的解决方案的方向吗?

4

2 回答 2

1

解决方法是使用MyBatis Interceptor 插件。例如,以下内容:

import java.sql.Connection;
import java.sql.Statement;
import java.util.Properties;

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.Plugin;
import org.apache.ibatis.plugin.Signature;

@Intercepts({@Signature(
        type=StatementHandler.class,
        method = "prepare",
        args={ Connection.class })})
public class StatementInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Connection conn = (Connection) invocation.getArgs()[0];
        Statement stmt = conn.createStatement();
        stmt.executeUpdate("SET QUERY_BAND = 'k=v;' FOR TRANSACTION;");
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {}
}
于 2011-06-24T14:57:31.553 回答
0

假设每个 SQL 字符串都应该附加到查询带中。我会尝试在 myBatis/Spring 中找到一个方法来做到这一点。使用 Spring 的 AOP 可以截获此方法,并将其结果附加到查询带并返回以供进一步计算。

找到一种拦截方法可能很困难,但并非不可能。下载所有依赖源并正确链接它们(使用 Maven 这应该是微不足道的,但在 Eclipse 中也不是那么难),在调试模式下运行代码并寻找合适的方法。

于 2011-06-23T09:24:00.493 回答