Skip to content

Latest commit

 

History

History
167 lines (145 loc) · 4.57 KB

MyBatis.page.plugin.md

File metadata and controls

167 lines (145 loc) · 4.57 KB

Pageable

/**
 * <pre>
 * 分页对象.
 * param参数为要查询的参数信息,如:username="zhangsan", 
 * name在MyBatis里面就是<if test="param.username != null"> ...
 * orders为数据排序信息, 可以多个,并且有序.
 * 其中total在MyBatis拦截器拦截会自动设置其值.
 * </pre>
 * @author luoyh(Roy) - Apr 26, 2017
 */
public class Pageable<T> implements Serializable {
	private static final long serialVersionUID = 1L;
	public static final int DEFAULT_START = 1;
	public static final int DEFAULT_SIZE = 20;
	
	private int start = DEFAULT_START;	// 当前页,从1开始
	private int size = DEFAULT_SIZE;	// 每页大小
	private int pages;	// 总页数
	private int total;	// 总大小
	
	private Map<String, Object> param = new HashMap<>();	// 参数列表
	private LinkedHashMap<String, Order> orders = new LinkedHashMap<>();	// 排序
	
	private List<T> data;	// 数据
	
	public static <T> Pageable<T> me() {
		return new Pageable<T>();
	}
	
	public static enum Order {
		ASC, DESC;
	}
	
	public LinkedHashMap<String, Order> getOrders() {
		return orders;
	}
	public void setOrders(LinkedHashMap<String, Order> orders) {
		this.orders = orders;
	}
	public int getStart() {
		return start;
	}
	public void setStart(Integer start) {
		this.start = null == start ? DEFAULT_START : start;
	}
	public int getSize() {
		return size;
	}
	public void setSize(Integer size) {
		this.size = null == size ? DEFAULT_SIZE : size;
	}
	public int getTotal() {
		return total;
	}
	public void setTotal(int total) {
		this.total = total;
	}
	public Map<String, Object> getParam() {
		return param;
	}
	public void setParam(Map<String, Object> param) {
		this.param = param;
	}
	public int getPages() {
		pages = total / size + (total % size == 0 ? 0 : 1);
		return pages;
	}
	public void setPages(int pages) {
		this.pages = pages;
	}
	public List<T> getData() {
		return data;
	}
	public void setData(List<T> data) {
		this.data = data;
	}
	
}

Oracle

/**
 * MyBatis page plugin.
 * @author luoyh(Roy) - Apr 26, 2017
 */
@Intercepts({
	@Signature(
			method = "prepare",
			type = StatementHandler.class,
			args = { Connection.class } // if +3.4, the arguments are two: Connection.class, Integer.class
)})
public class PageInterceptor implements Interceptor {
	
	private String seprator;
	private int sepratorLength = 0;

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
		BoundSql boundSql = statementHandler.getBoundSql();
		Object param = boundSql.getParameterObject();
		
		if (param instanceof Pageable) {
			MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
			String origin = boundSql.getSql();
			int index = origin.indexOf(seprator);
			
			String prefix = origin.substring(0, index);
			StringBuilder suffix = new StringBuilder(origin.substring(index + sepratorLength));
			
			Pageable<?> page = (Pageable<?>) param;
			
			String total = "select count(1) from " + suffix.toString();
			Connection connection = (Connection) invocation.getArgs()[0]; // don't close
			try (PreparedStatement countStatement = connection.prepareStatement(total)) {
				ParameterHandler parameterHandler = (ParameterHandler)metaObject.getValue("delegate.parameterHandler");
				parameterHandler.setParameters(countStatement);
				try (ResultSet rs = countStatement.executeQuery()) {
					if(rs.next()) {
						page.setTotal(rs.getInt(1));
					}
				}
			}
			
			// append order by.
			if (!page.getOrders().isEmpty()) {
				suffix.append(" order by ");
				int idx = 0;
				for (Map.Entry<String, Order> entry : page.getOrders().entrySet()) {
					if (idx ++ > 0) {
						suffix.append(" , ");
					}
					suffix.append(entry.getKey()).append(" ").append(entry.getValue().name());
				}
			}
			
                        // if MySQL, use limit or offset, it's easy.
			StringBuilder sql = new StringBuilder();
			sql.append("select * from (select ROWNUM rw, a.* from ( ").append(prefix).append(" from ")
			.append(suffix).append(") a where rownum < ").append(page.getStart() * page.getSize() + 1)
			.append(") b where b.rw > ").append((page.getStart() - 1) * page.getSize());
			
			metaObject.setValue("delegate.boundSql.sql", sql.toString());
		}
		return invocation.proceed();
	}

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

	@Override
	public void setProperties(Properties properties) {
		// like %from% #FRoM# $foRM$ _form_ , default FROM
		// first FROM
		this.seprator = properties.getProperty("seprator", "FROM");
		this.sepratorLength = this.seprator.length();
	}

}