`

mybatis 分页 使用拦截器sql重写

阅读更多

 

package cn.util;

import java.sql.Connection;
import java.util.Properties;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.reflect.FieldUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
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;
import org.apache.ibatis.session.RowBounds;

/**
 * 分页拦截器
 * @author
 *
 */
@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}))
public class PageInterceptor implements Interceptor {
 
 private final String SQL_SELECT = "(?is)^\\s*SELECT.*$";
 private final String SQL_COUNT  = "(?is)^\\s*SELECT\\s+COUNT\\s*\\(\\s*(?:\\*|\\w+)\\s*\\).*$";

 public Object intercept(Invocation inv) throws Throwable {

  StatementHandler target = (StatementHandler) inv.getTarget();
  BoundSql boundSql = target.getBoundSql();
  String sql = boundSql.getSql();
  if(StringUtils.isBlank(sql)){
   return inv.proceed();
  }
  
  System.out.println("SQL: "+ sql);
  
  //只有select语句下一步
  if(sql.matches(SQL_SELECT) && !Pattern.matches(SQL_COUNT, sql)){
   Object obj = FieldUtils.readField(target, "delegate", true);
   //反射获取RowBounds对象
   RowBounds rowBounds = (RowBounds) FieldUtils.readField(obj, "rowBounds", true);
   //分页参数存在且不为默认值时进行分页SQL构造
   if(rowBounds != null && rowBounds != RowBounds.DEFAULT){
    FieldUtils.writeField(boundSql, "sql", newSql(sql, rowBounds), true);
    System.out.println("new Sql: "+boundSql.getSql());
    FieldUtils.writeField(rowBounds ,"offset", RowBounds.NO_ROW_OFFSET, true);
    FieldUtils.writeField(rowBounds, "limit", RowBounds.NO_ROW_LIMIT, true);
   }
  }
  return inv.proceed();
 }


 public Object plugin(Object target) {

  return Plugin.wrap(target, this);
 }

 public void setProperties(Properties arg0) {

  System.out.println("PageInterceptor setProperties arg0="+ arg0);
 }
 
 /**Oracle 分页
 public String newSql(String oldSql, RowBounds rowBounds){
  StringBuffer sb = new StringBuffer(128);
  sb.append(" SELECT * FROM (SELECT row_.*, ROWNUM rownum_ FROM (");
  sb.append(oldSql);
  sb.append(") row_ WHERE ROWNUM <=");
  sb.append(rowBounds.getLimit());
  sb.append(") WHERE rownum_ > ");
  sb.append(rowBounds.getOffset());
  return sb.toString();
 }
 */
 
 /**mysql 分页*/
 public String newSql(String oldSql, RowBounds rowBounds){
  StringBuffer sb = new StringBuffer(128);
  sb.append(oldSql);
  sb.append(" limit ");
  sb.append(rowBounds.getOffset());
  sb.append(",");
  sb.append(rowBounds.getLimit());
  
  return sb.toString();
 }

}

<select id="findUsersOfPage" resultMap="userMap" parameterType="userDomain">
  select
  <include refid="userFields"></include>
  from user
  where 1=1
  <if test="userName !=null">
   and USERNAME like '%' || #{userName} || '%'
  </if>
 </select>

 

@Repository
public interface UserMapper {

  
  //分页(使用拦截器sql重写)
 public List<User> findUsersOfPage(User user, RowBounds rowBounds);
}

 

@Service
public class UserServiceImpl implements UserService {
 
 @Autowired
 private UserMapper userMapper;

 public List<User> findUsers() {

  return userMapper.select();
 }
 
 @Transactional
 public void insert(User user){
  userMapper.insert(user);
 }

 //事务传播行为:REQUIRED、REQUIRES_NEW、NESTED 作为testTran方法的一个整体,要么执行成功,要么失败,抛出异常则回滚。
 //@Transactional(propagation=Propagation.REQUIRED, rollbackForClassName={"Exception"})
 //@Transactional(propagation=Propagation.REQUIRES_NEW, rollbackForClassName={"Exception"})
 //@Transactional(propagation=Propagation.NESTED, rollbackForClassName={"Exception"})
 
 //无事务
 //@Transactional(propagation=Propagation.SUPPORTS, rollbackForClassName={"Exception"})
 //@Transactional(propagation=Propagation.NOT_SUPPORTED, rollbackForClassName={"Exception"})
 //@Transactional(propagation=Propagation.NEVER, rollbackForClassName={"Exception"})
 
 @Transactional(propagation=Propagation.REQUIRED, rollbackForClassName={"Exception"})
 public List<User> testTran(User user)throws Exception{
  insert(user);
  List<User> users = findUsers();
  if(true)
   throw new Exception("transaction");
  return users;
 }
 
 
 //分页(使用拦截器sql重写)
 public List<User> findUsersOfPage(User user, int offset, int limit){
  return userMapper.findUsersOfPage(user, new RowBounds(offset, limit));
 }
 
}

分享到:
评论

相关推荐

    mybatis分页拦截器(自动封装版)剖析.pdf

    在自动封装版的MyBatis分页拦截器中,开发者通常会创建一个拦截器类,该类会拦截到执行SQL的时机,然后在SQL语句中动态添加分页相关的条件,如LIMIT和OFFSET子句,以实现数据的分页展示。 分页拦截器的核心思想是...

    mybatis使用拦截器实现分页操作

    以下是实现分页拦截器的基本步骤: 1. **创建拦截器类**:首先,我们需要创建一个实现了`Interceptor`接口的类,例如`PageInterceptor`。在该类中,我们需要重写`intercept`方法,此方法会在每次执行SQL语句之前被...

    Mybatis学习- 拦截器-实现分页

    在Mybatis框架中,拦截器(Interceptor)是一个强大的工具,它可以让我们在Mybatis执行SQL之前或之后做一些额外的操作,比如日志记录、权限检查、事务管理等。在本主题中,我们将深入探讨如何利用Mybatis的拦截器...

    mybatis拦截器分页

    4. **使用分页拦截器**: - 在服务层或 DAO 层,当调用查询方法时,不再需要显式编写分页 SQL,只需传递分页参数即可。拦截器会在背后自动处理这些细节。 5. **性能优化**: - 分页拦截器还可以用于优化查询性能...

    MyBatis 分页源码简单

    在 PageHelper 插件中,主要通过拦截器机制实现分页功能。当执行 SQL 查询时,`PageInterceptor` 会拦截到这个过程,然后根据分页参数(如 `@Page` 注解)动态生成分页 SQL。在 MySQL 中,这通常意味着在原始 SQL ...

    Mybatis拦截器介绍及分页插件

    ### Mybatis拦截器介绍及分页插件 #### 1.2 前言 在Mybatis中,拦截器提供了一种强大的机制,允许开发者在不修改框架核心代码的情况下增加自定义逻辑。例如,可以通过创建拦截器来实现日志记录、性能监控、事务...

    MyBatis拦截器实现分页功能的实现方法

    分页拦截器需要实现MyBatis提供的Interceptor接口,并重写intercept方法,以便在SQL执行前进行拦截。在intercept方法中,需要根据Page对象计算出的参数(dbIndex和dbNumber)来修改原始的SQL语句,添加分页逻辑。...

    pring_mybatis物理分页

    - 编写分页拦截器,实现`Interceptor`接口,重写`intercept()`方法,这里会处理SQL的分页逻辑。 - 在Spring的配置文件中配置拦截器,如`&lt;bean id="pageInterceptor" class="com.example.PageInterceptor"&gt;`。 - 在...

    mybatis插件分页测试

    例如,可以使用PageHelper插件,它是一个非常流行的MyBatis分页插件,支持多种数据库。 ```xml &lt;!-- other properties --&gt; ``` 2. **分页参数**:在服务层或者DAO层,我们需要传递分页参数到Mapper的查询...

    SSM+拦截器分页

    1. **创建拦截器类**:实现HandlerInterceptor接口,重写preHandle、postHandle和afterCompletion方法。 2. **注册拦截器**:在SpringMVC的配置文件中,通过标签注册自定义的拦截器。 3. **配置拦截路径**:在拦截...

    mybatis 自定义分页插件.rar

    本压缩包“mybatis 自定义分页插件.rar”提供了关于如何利用MyBatis的拦截器实现自定义分页查询的实践案例。 首先,我们需要理解MyBatis的拦截器(Interceptor)。拦截器是MyBatis动态代理机制的一部分,它允许我们...

    mybatis3 物理分页源代码

    本主题将深入探讨Mybatis3中如何实现物理分页,特别是通过拦截器来实现这一功能。 首先,我们来看Interceptor接口。在Mybatis中,拦截器扮演着关键角色,它允许我们在特定的执行点(如SQL语句的准备、执行等)插入...

    mybatis-pagination-master

    《MyBatis分页插件mybatis-pagination深度解析》 在大数据量的Web应用中,分页查询是不可或缺的一部分,它能有效提高系统的性能并优化用户体验。MyBatis作为一款强大的持久层框架,虽然提供了基本的SQL映射功能,但...

    mybatis-plugins

    MyBatis-Plugins是一款增强MyBatis框架功能的插件工具,它允许开发者自定义拦截器,对MyBatis的SQL执行过程进行拦截和修改,从而实现如日志记录、性能分析、动态SQL等功能。这款插件使得在不修改MyBatis核心源码的...

    修改mybatis的MBG工具源码,支持mysql分页

    MBG 是一个强大的代码生成器,能够自动根据数据库表结构生成MyBatis的Mapper接口、XML配置文件以及实体类,极大地减少了开发中的重复工作。 描述中提到的“NULL”可能是因为原始信息缺失,但我们可以通过常规流程来...

    MyBatis实现物理分页的实例

    3. 使用插件时,确保正确配置 MyBatis 的拦截器链,避免与其他插件冲突。 4. 为了防止 SQL 注入,修改 SQL 时应确保参数安全,最好使用预编译的 PreparedStatement。 总之,MyBatis 的物理分页可以通过自定义插件...

    mybatis interceptor

    5. **使用分页拦截器**:在服务层或 DAO 层,我们不再需要显式地处理分页逻辑,只需提供查询方法和所需的分页参数即可。拦截器会自动为我们处理分页操作。 通过以上步骤,我们就成功地实现了基于 MyBatis ...

    MyBatis面试题1

    使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke() 方法发现 a.getB() 是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 SQL,...

    spring+springmvc+mybatis+framemarker的基础上添加分页功能

    综上所述,"spring+springmvc+mybatis+framemarker"的组合提供了一个强大的Web应用开发基础,添加分页功能和拦截器进一步提升了系统的实用性和安全性。理解并熟练掌握这些技术,将有助于我们构建出高质量、易维护的...

Global site tag (gtag.js) - Google Analytics