mybatis+springMvc
2015-08-17 10:56
295 查看
1.在xml配置文件中配置插件 来拦截分页请求
<plugins>
<plugin interceptor="com.CQMarketSupervise.common.PaginationInterceptor" />
</plugins>
2.拦截
在我的实现里大量使用了MetaObject这个对象,因此有必要先介绍下它。MetaObject是Mybatis提供的一个的工具类,通过它包装一个对象后可以获取或设置该对象的原本不可访问的属性(比如那些私有属性)。它有个三个重要方法经常用到:
1) MetaObject forObject(Object object,ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory)
2) Object getValue(String name)
3) void setValue(String name, Object value)
方法1)用于包装对象;方法2)用于获取属性的值(支持OGNL的方法);方法3)用于设置属性的值(支持OGNL的方法);
/** * * 分页拦截器,用于拦截需要进行分页查询的操作,然后对其进行分页处理。 * 利用拦截器实现Mybatis分页的原理: * 要利用JDBC对数据库进行操作就必须要有一个对应的Statement对象,Mybatis在执行Sql语句前就会产生一个包含Sql语句的Statement对象,而且对应的Sql语句 * 是在Statement之前产生的,所以我们就可以在它生成Statement之前对用来生成Statement的Sql语句下手。在Mybatis中Statement语句是通过RoutingStatementHandler对象的 * prepare方法生成的。所以利用拦截器实现Mybatis分页的一个思路就是拦截StatementHandler接口的prepare方法,然后在拦截器方法中把Sql语句改成对应的分页查询Sql语句,之后再调用 * StatementHandler对象的prepare方法,即调用invocation.proceed()。 * 对于分页而言,在拦截器里面我们还需要做的一个操作就是统计满足当前条件的记录一共有多少,这是通过获取到了原始的Sql语句后,把它改为对应的统计语句再利用Mybatis封装好的参数和设 * 置参数的功能把Sql语句中的参数进行替换,之后再执行查询记录数的Sql语句进行总记录数的统计。 * */
@Intercepts( { @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PaginationInterceptor implements Interceptor {
private final static Log log = LogFactory
.getLog(PaginationInterceptor.class);
//对于StatementHandler其实只有两个实现类,一个是RoutingStatementHandler,另一个是抽象类BaseStatementHandler, //BaseStatementHandler有三个子类,分别是SimpleStatementHandler,PreparedStatementHandler和CallableStatementHandler, //SimpleStatementHandler是用于处理Statement的,PreparedStatementHandler是处理PreparedStatement的,而CallableStatementHandler是 //处理CallableStatement的。Mybatis在进行Sql语句处理的时候都是建立的RoutingStatementHandler,而在RoutingStatementHandler里面拥有一个 //StatementHandler类型的delegate属性,RoutingStatementHandler会依据Statement的不同建立对应的BaseStatementHandler,即SimpleStatementHandler、 //PreparedStatementHandler或CallableStatementHandler,在RoutingStatementHandler里面所有StatementHandler接口方法的实现都是调用的delegate对应的方法。 //我们在PageInterceptor类上已经用@Signature标记了该Interceptor只拦截StatementHandler接口的prepare方法,又因为Mybatis只有在建立RoutingStatementHandler的时候 //是通过Interceptor的plugin方法进行包裹的,所以我们这里拦截到的目标对象肯定是RoutingStatementHandler对象。
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation
.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
MetaObject metaStatementHandler = MetaObject.forObject(
statementHandler, new DefaultObjectFactory(),
new DefaultObjectWrapperFactory());
RowBounds rowBounds = (RowBounds) metaStatementHandler
.getValue("delegate.rowBounds");
if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
return invocation.proceed();
}
Configuration configuration = (Configuration) metaStatementHandler
.getValue("delegate.configuration");
Dialect.Type databaseType = null;
try {
databaseType = Dialect.Type.valueOf(configuration.getVariables()
.getProperty("dialect").toUpperCase());
} catch (Exception e) {
// ignore
}
if (databaseType == null) {
throw new RuntimeException(
"the value of the dialect property in configuration.xml is not defined : "
+ configuration.getVariables().getProperty(
"dialect"));
}
Dialect dialect = null;
switch (databaseType) {
case MYSQL:
dialect = new MysqlDialect();
break;
case ORACLE:
dialect = new OracleDialect();
break;
case SQLSERVER:
dialect = new SQLServerDialect();
break;
}
String originalSql = (String) metaStatementHandler
.getValue("delegate.boundSql.sql");
metaStatementHandler.setValue("delegate.boundSql.sql", dialect
.getLimitString(originalSql, rowBounds.getOffset(), rowBounds
.getLimit()));
metaStatementHandler.setValue("delegate.rowBounds.offset",
RowBounds.NO_ROW_OFFSET);
metaStatementHandler.setValue("delegate.rowBounds.limit",
RowBounds.NO_ROW_LIMIT);
if (log.isDebugEnabled()) {
log.debug("生成分页SQL : " + boundSql.getSql());
}
return invocation.proceed();
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}
------------------------------------------------------------------------------------
public abstract class Dialect {
public static enum Type {
MYSQL, ORACLE,SQLSERVER
}
public abstract String getLimitString(String sql, int offset, int limit);
}
------------------------------------------------------------------------------------
public class OracleDialect extends Dialect {
@Override
public String getLimitString(String sql, int offset, int limit) {
// TODO Auto-generated method stub
sql = sql.trim();
StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);
pagingSelect
.append("select * from ( select row_.*, rownum rownum_ from ( ");
pagingSelect.append(sql);
pagingSelect.append(" ) row_ ) where rownum_ > ").append(offset)
.append(" and rownum_ <= ").append(offset + limit);
return pagingSelect.toString();
}
}
/**
* 通用分页模型
* @author wt
*
*/
public class PageInfo {
/**
* 总条数
*/
private int total;
/**
* 总页数
*/
private int pageTotal;
/**
* 当前页
*/
private int currPageNo;
/**
* 每页条数
*/
private int pageSize;
/**
* 当前页详细数据
*/
private List rows = new ArrayList();
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getPageTotal() {
return pageTotal;
}
public void setPageTotal(int pageTotal) {
this.pageTotal = pageTotal;
}
public int getCurrPageNo() {
return currPageNo;
}
public void setCurrPageNo(int currPageNo) {
this.currPageNo = currPageNo;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public List getRows() {
return rows;
}
public void setRows(List rows) {
this.rows = rows;
}
}
-------------------------------------------------------------------------------------
private static final Logger log = Logger.getLogger(CommonServiceImpl.class);
@Resource(name = "sqlSessionFactory")
private DefaultSqlSessionFactory fb;
public PageInfo getPage(String detailSqlId, String countSqlId, Object obj,
int pageNo, int pageSize) {
return getPage(detailSqlId, countSqlId, obj, pageNo, pageSize, 1);
}
public PageInfo getPage(String detailSqlId, String countSqlId, Object obj,
int pageNo, int pageSize, int fetchNum) {
PageInfo page = new PageInfo();
page.setCurrPageNo(pageNo);
page.setPageSize(pageSize);
SqlSession ss = null;
int cruuPageNo = page.getCurrPageNo();
try {
ss = fb.openSession();
if (cruuPageNo < 1) {
cruuPageNo = 1;
}
Object oo = ss.selectOne(countSqlId, obj);
int cnt = new Integer(oo.toString());
int pageTotal = cnt % page.getPageSize() == 0 ? cnt
/ page.getPageSize() : (cnt / page.getPageSize() + 1);
page.setTotal(cnt);
page.setPageTotal(pageTotal);
int offset = (cruuPageNo - 1) * page.getPageSize();
RowBounds bounds = new RowBounds(offset, page.getPageSize()
* fetchNum);
page.setCurrPageNo(cruuPageNo);
page.setRows(ss.selectList(detailSqlId, obj, bounds));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
ss.close();
}
log.debug(JsonUtil.object2json(page));
return page;
}
<plugins>
<plugin interceptor="com.CQMarketSupervise.common.PaginationInterceptor" />
</plugins>
2.拦截
MetaObject简介
在我的实现里大量使用了MetaObject这个对象,因此有必要先介绍下它。MetaObject是Mybatis提供的一个的工具类,通过它包装一个对象后可以获取或设置该对象的原本不可访问的属性(比如那些私有属性)。它有个三个重要方法经常用到:1) MetaObject forObject(Object object,ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory)
2) Object getValue(String name)
3) void setValue(String name, Object value)
方法1)用于包装对象;方法2)用于获取属性的值(支持OGNL的方法);方法3)用于设置属性的值(支持OGNL的方法);
/** * * 分页拦截器,用于拦截需要进行分页查询的操作,然后对其进行分页处理。 * 利用拦截器实现Mybatis分页的原理: * 要利用JDBC对数据库进行操作就必须要有一个对应的Statement对象,Mybatis在执行Sql语句前就会产生一个包含Sql语句的Statement对象,而且对应的Sql语句 * 是在Statement之前产生的,所以我们就可以在它生成Statement之前对用来生成Statement的Sql语句下手。在Mybatis中Statement语句是通过RoutingStatementHandler对象的 * prepare方法生成的。所以利用拦截器实现Mybatis分页的一个思路就是拦截StatementHandler接口的prepare方法,然后在拦截器方法中把Sql语句改成对应的分页查询Sql语句,之后再调用 * StatementHandler对象的prepare方法,即调用invocation.proceed()。 * 对于分页而言,在拦截器里面我们还需要做的一个操作就是统计满足当前条件的记录一共有多少,这是通过获取到了原始的Sql语句后,把它改为对应的统计语句再利用Mybatis封装好的参数和设 * 置参数的功能把Sql语句中的参数进行替换,之后再执行查询记录数的Sql语句进行总记录数的统计。 * */
@Intercepts( { @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PaginationInterceptor implements Interceptor {
private final static Log log = LogFactory
.getLog(PaginationInterceptor.class);
//对于StatementHandler其实只有两个实现类,一个是RoutingStatementHandler,另一个是抽象类BaseStatementHandler, //BaseStatementHandler有三个子类,分别是SimpleStatementHandler,PreparedStatementHandler和CallableStatementHandler, //SimpleStatementHandler是用于处理Statement的,PreparedStatementHandler是处理PreparedStatement的,而CallableStatementHandler是 //处理CallableStatement的。Mybatis在进行Sql语句处理的时候都是建立的RoutingStatementHandler,而在RoutingStatementHandler里面拥有一个 //StatementHandler类型的delegate属性,RoutingStatementHandler会依据Statement的不同建立对应的BaseStatementHandler,即SimpleStatementHandler、 //PreparedStatementHandler或CallableStatementHandler,在RoutingStatementHandler里面所有StatementHandler接口方法的实现都是调用的delegate对应的方法。 //我们在PageInterceptor类上已经用@Signature标记了该Interceptor只拦截StatementHandler接口的prepare方法,又因为Mybatis只有在建立RoutingStatementHandler的时候 //是通过Interceptor的plugin方法进行包裹的,所以我们这里拦截到的目标对象肯定是RoutingStatementHandler对象。
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation
.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
MetaObject metaStatementHandler = MetaObject.forObject(
statementHandler, new DefaultObjectFactory(),
new DefaultObjectWrapperFactory());
RowBounds rowBounds = (RowBounds) metaStatementHandler
.getValue("delegate.rowBounds");
if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
return invocation.proceed();
}
Configuration configuration = (Configuration) metaStatementHandler
.getValue("delegate.configuration");
Dialect.Type databaseType = null;
try {
databaseType = Dialect.Type.valueOf(configuration.getVariables()
.getProperty("dialect").toUpperCase());
} catch (Exception e) {
// ignore
}
if (databaseType == null) {
throw new RuntimeException(
"the value of the dialect property in configuration.xml is not defined : "
+ configuration.getVariables().getProperty(
"dialect"));
}
Dialect dialect = null;
switch (databaseType) {
case MYSQL:
dialect = new MysqlDialect();
break;
case ORACLE:
dialect = new OracleDialect();
break;
case SQLSERVER:
dialect = new SQLServerDialect();
break;
}
String originalSql = (String) metaStatementHandler
.getValue("delegate.boundSql.sql");
metaStatementHandler.setValue("delegate.boundSql.sql", dialect
.getLimitString(originalSql, rowBounds.getOffset(), rowBounds
.getLimit()));
metaStatementHandler.setValue("delegate.rowBounds.offset",
RowBounds.NO_ROW_OFFSET);
metaStatementHandler.setValue("delegate.rowBounds.limit",
RowBounds.NO_ROW_LIMIT);
if (log.isDebugEnabled()) {
log.debug("生成分页SQL : " + boundSql.getSql());
}
return invocation.proceed();
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}
------------------------------------------------------------------------------------
public abstract class Dialect {
public static enum Type {
MYSQL, ORACLE,SQLSERVER
}
public abstract String getLimitString(String sql, int offset, int limit);
}
------------------------------------------------------------------------------------
public class OracleDialect extends Dialect {
@Override
public String getLimitString(String sql, int offset, int limit) {
// TODO Auto-generated method stub
sql = sql.trim();
StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);
pagingSelect
.append("select * from ( select row_.*, rownum rownum_ from ( ");
pagingSelect.append(sql);
pagingSelect.append(" ) row_ ) where rownum_ > ").append(offset)
.append(" and rownum_ <= ").append(offset + limit);
return pagingSelect.toString();
}
}
/**
* 通用分页模型
* @author wt
*
*/
public class PageInfo {
/**
* 总条数
*/
private int total;
/**
* 总页数
*/
private int pageTotal;
/**
* 当前页
*/
private int currPageNo;
/**
* 每页条数
*/
private int pageSize;
/**
* 当前页详细数据
*/
private List rows = new ArrayList();
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getPageTotal() {
return pageTotal;
}
public void setPageTotal(int pageTotal) {
this.pageTotal = pageTotal;
}
public int getCurrPageNo() {
return currPageNo;
}
public void setCurrPageNo(int currPageNo) {
this.currPageNo = currPageNo;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public List getRows() {
return rows;
}
public void setRows(List rows) {
this.rows = rows;
}
}
-------------------------------------------------------------------------------------
private static final Logger log = Logger.getLogger(CommonServiceImpl.class);
@Resource(name = "sqlSessionFactory")
private DefaultSqlSessionFactory fb;
public PageInfo getPage(String detailSqlId, String countSqlId, Object obj,
int pageNo, int pageSize) {
return getPage(detailSqlId, countSqlId, obj, pageNo, pageSize, 1);
}
public PageInfo getPage(String detailSqlId, String countSqlId, Object obj,
int pageNo, int pageSize, int fetchNum) {
PageInfo page = new PageInfo();
page.setCurrPageNo(pageNo);
page.setPageSize(pageSize);
SqlSession ss = null;
int cruuPageNo = page.getCurrPageNo();
try {
ss = fb.openSession();
if (cruuPageNo < 1) {
cruuPageNo = 1;
}
Object oo = ss.selectOne(countSqlId, obj);
int cnt = new Integer(oo.toString());
int pageTotal = cnt % page.getPageSize() == 0 ? cnt
/ page.getPageSize() : (cnt / page.getPageSize() + 1);
page.setTotal(cnt);
page.setPageTotal(pageTotal);
int offset = (cruuPageNo - 1) * page.getPageSize();
RowBounds bounds = new RowBounds(offset, page.getPageSize()
* fetchNum);
page.setCurrPageNo(cruuPageNo);
page.setRows(ss.selectList(detailSqlId, obj, bounds));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
ss.close();
}
log.debug(JsonUtil.object2json(page));
return page;
}
相关文章推荐
- Java job 定时器
- Java中线程总结
- 《Java设计模式》之调停者模式(Mediator)
- Spring 学习笔记(五)——MVC
- springmvc国际化实现方法
- java小游戏-坦克大战,事后总结
- Spring MVC 解读——@Autowired、@Controller、@Service从原理层面来分析
- Spring---AOP应用
- 解决myeclipse在mac中Retina屏幕中模糊的终极详细方法
- [Java]Contains Duplicate II 包含重复数字
- java的事务处理
- Spring MVC入门
- struts2国际化开发详细过程
- java json
- 一段网上java常见escape和unescape方法的BUG
- java学习笔记-----qq项目----在服务器端实现两个客户端的通信的原理
- spring MVC 使用注解返回json
- Java数据类型的转换:隐式(自动)转换与强制转换
- 选择排序法--java实现
- Java compiler level does not match the version of the instal