Mybatis拦截器分页

使用拦截器

Web开发中我们经常会碰到分页操作,一个项目中或许有多处使用到分页,这时如果Java后台使用MyBatis作为持久层,我们就可以使用MyBatis的拦截器功能来完成整个项目中多处的分页操作,减少代码的冗余。

拦截器代码:

//拦截StatementHandler中参数类型为Connection的prepare方法
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})})
public class PageInterceptor implements Interceptor {

    private String test; // 获取xml中配置的属性

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
        //通过MetaObject优雅访问对象的属性,这里是访问statementHandler的属性
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
        //先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
        MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
        // 配置文件中SQL语句的ID
        String id = mappedStatement.getId();
        if(id.matches(".+ByPage$")) { //需要拦截的ID(正则匹配)
            BoundSql boundSql = statementHandler.getBoundSql();
            // 原始的SQL语句
            String sql = boundSql.getSql();
            // 查询总条数的SQL语句
            String countSql = "select count(*) from (" + sql + ")a";
            //执行总条数SQL语句的查询
            Connection connection = (Connection)invocation.getArgs()[0];
            PreparedStatement countStatement = connection.prepareStatement(countSql);
            ////获取参数信息即where语句的条件信息,注意上面拿到的sql中参数还是用?代替的
            ParameterHandler parameterHandler = (ParameterHandler)metaObject.getValue("delegate.parameterHandler");
            parameterHandler.setParameters(countStatement);
            ResultSet rs = countStatement.executeQuery();

            Map<?,?> parameter = (Map<?,?>)boundSql.getParameterObject();
            Page page = (Page)parameter.get("page");
            if(rs.next()) {
                page.setTotalNumber(rs.getInt(1));
            }
            // 改造后带分页查询的SQL语句
            String pageSql = sql + " limit " + page.getDbIndex() + "," + page.getDbNumber();
            metaObject.setValue("delegate.boundSql.sql", pageSql);
        }
        return invocation.proceed();
    }

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

    @Override
    public void setProperties(Properties properties) {
        this.test = properties.getProperty("test");
        // TODO Auto-generated method stub
    }

}

MetaObject是Mybatis提供的一个用于方便、优雅访问对象属性的对象,通过它可以简化代码、不需要try/catch各种reflect异常,同时它支持对JavaBean、Collection、Map三种类型对象的操作。获取MetaObject对象需要使用静态方法MetaObject.forObject,并且需要指定ObjectFactory , ObjectWrapperFactory , ReflectorFactory(3.3.0之前不需要)。

配置拦截器:

<plugins>
    <plugin interceptor="com.chm.inteceptor.PageInterceptor">
        <property name="test" value="abc"/>
    </plugin>
</plugins>

这里配置test的值为abc,那么上面拦截器中test的就会被赋值为abc。

查询SQL:

<select id="queryMessageListByPage" parameterType="java.util.Map" resultMap="MessageResult">
 select <include refid="columns"/> from MESSAGE
  <where>
    <if test="message.command != null and !&quot;&quot;.equals(message.command.trim())">
    and COMMAND=#{message.command}
   </if>
   <if test="message.description != null and !&quot;&quot;.equals(message.description.trim())">
    and DESCRIPTION like '%' #{message.description} '%'
   </if>
  </where>
  order by ID
</select>

<sql id="columns">ID,COMMAND,DESCRIPTION,CONTENT</sql>

调用示例:

/**
 * 根据查询条件分页查询消息列表
 */
public List<Message> queryMessageListByPage(String command,String description,Page page) {
    Map<String,Object> parameter = new HashMap<String, Object>();
    // 组织消息对象
    Message message = new Message();
    message.setCommand(command);
    message.setDescription(description);
    parameter.put("message", message);
    parameter.put("page", page);
    MessageDao messageDao = new MessageDao();
    // 分页查询并返回结果
    return messageDao.queryMessageListByPage(parameter);
}

猜你喜欢

转载自blog.csdn.net/luzhensmart/article/details/83105628