- 浏览: 123414 次
- 性别:
- 来自: 深圳、重庆
文章分类
最新评论
-
张飞1:
你好!,看了你这篇文章,然后阅读了一下源码,在XMLConfi ...
mybatis分页实现2 -
icefire:
yuyuanpei 写道博主,我理解RowBounds是理想记 ...
mybatis分页实现1 -
yuyuanpei:
博主,我理解RowBounds是理想记录数从第几条到第几条的, ...
mybatis分页实现1 -
anglny:
你定义一个所有实体对象的父实体。然后在里面定义一个total的 ...
mybatis分页实现2 -
icefire:
clxy 写道我也在找这个实现。你这里的方法有些“繁琐”,需要 ...
mybatis分页实现2
前一篇写了如何实现sql分页
http://icefire.iteye.com/blogs/1028915
这一篇讲,如何实现一个mapping的方法访问,自动返回page数据,也就是自读计算分页总数。
先看成果对比效果
原先
现在
如果看源码,会发现,mapping接口自动代理涉及Configuration,MapperRegistry,MapperProxy,MapperMethod。
其中比较可惜的是,MapperProxy,MapperMethod完全无法重用,只能参考其中代码自己来实现了。还有那个mybatis通过的spring集成类SqlSessionFactoryBean,由于要实现自己Configuration,也导致SqlSessionFactoryBean无法重用。这点上,和spring比较起来,就差太多了。
MyConfiguration
PaginationMapperRegistry
PaginationMapperProxy
PaginationMapperMethod
具体某个查询的SQL配置
补代码Pagination,分页辅助类
目前无可避免的需要两段sql。在考虑如何实现自动生成count(*),但目前做到这样,已经达到自己的预期了。暂时先就这样吧!
粗略看了下,你提供的这个应该会好些,比较适合用到项目中。我这个就自己业余写的demo,实际项目使用还差得多。自己工作也没使用mybatis,也就没继续深入了。
不知道你的需求是怎样的,如果用spring,就没必要用xml来初始化Configuration了。如果是xml要增加自己的属性,可能需要扩展XMLConfigBuilder吧,具体没研究过了。我使用自己的Configuration是因为我要替换其中的属性,Configuration又没提供set方法,所以别无选择。
http://icefire.iteye.com/blogs/1028915
引用
本文对直接使用sqlsession的方式无参考价值,本文只针对只写接口和XML文件的方式
这一篇讲,如何实现一个mapping的方法访问,自动返回page数据,也就是自读计算分页总数。
先看成果对比效果
原先
public interface HelloMapping { public List<Hello> findAll(RowBounds rowBounds); public Long findAllCount(); }
public String list(@ModelAttribute Pagination<Hello> pagination,Model model) { pagination.setTotal(helloMapping.findAllCount()); pagination.setList(helloMapping.findAll(pagination.newRowBounds()))); model.addAttribute("paging", pagination); return "/hello/view/list"; }
现在
public interface HelloMapping { public Pagination<Hello> findAll(Pagination<Hello> pagination); }
public String list(@ModelAttribute Pagination<Hello> pagination,Model model) { model.addAttribute("paging", helloMapping.findAll(pagination)); return "/hello/view/list"; }
如果看源码,会发现,mapping接口自动代理涉及Configuration,MapperRegistry,MapperProxy,MapperMethod。
其中比较可惜的是,MapperProxy,MapperMethod完全无法重用,只能参考其中代码自己来实现了。还有那个mybatis通过的spring集成类SqlSessionFactoryBean,由于要实现自己Configuration,也导致SqlSessionFactoryBean无法重用。这点上,和spring比较起来,就差太多了。
MyConfiguration
public class MyConfiguration extends Configuration { protected MapperRegistry mapperRegistry = new PaginationMapperRegistry(this); public <T> void addMapper(Class<T> type) { mapperRegistry.addMapper(type); } public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); } @SuppressWarnings("rawtypes") public boolean hasMapper(Class type) { return mapperRegistry.hasMapper(type); } }
PaginationMapperRegistry
public class PaginationMapperRegistry extends MapperRegistry { public PaginationMapperRegistry(Configuration config) { super(config); } public <T> T getMapper(Class<T> type, SqlSession sqlSession) { if (!hasMapper(type)) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } try { return PaginationMapperProxy.newMapperProxy(type, sqlSession); } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } } }
PaginationMapperProxy
public class PaginationMapperProxy implements InvocationHandler { private static final Set<String> OBJECT_METHODS = new HashSet<String>() { private static final long serialVersionUID = -1782950882770203583L; { add("toString"); add("getClass"); add("hashCode"); add("equals"); add("wait"); add("notify"); add("notifyAll"); } }; private boolean isObjectMethod(Method method) { return OBJECT_METHODS.contains(method.getName()); } private SqlSession sqlSession; private <T> PaginationMapperProxy(SqlSession sqlSession) { this.sqlSession = sqlSession; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (isObjectMethod(method)) { return null; } final Class<?> declaringInterface = findDeclaringInterface(proxy, method); if (Pagination.class.isAssignableFrom(method.getReturnType())) { // 分页处理 return new PaginationMapperMethod(declaringInterface, method, sqlSession).execute(args); } // 原处理方式 final MapperMethod mapperMethod = new MapperMethod(declaringInterface, method, sqlSession); final Object result = mapperMethod.execute(args); if (result == null && method.getReturnType().isPrimitive()) { throw new BindingException( "Mapper method '" + method.getName() + "' (" + method.getDeclaringClass() + ") attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; } private Class<?> findDeclaringInterface(Object proxy, Method method) { Class<?> declaringInterface = null; for (Class<?> iface : proxy.getClass().getInterfaces()) { Method m = ReflectionUtils.findMethod(iface, method.getName(), method.getParameterTypes()); if (m != null) { declaringInterface = iface; } } if (declaringInterface == null) { throw new BindingException( "Could not find interface with the given method " + method); } return declaringInterface; } @SuppressWarnings("unchecked") public static <T> T newMapperProxy(Class<T> mapperInterface, SqlSession sqlSession) { ClassLoader classLoader = mapperInterface.getClassLoader(); Class<?>[] interfaces = new Class[] { mapperInterface }; PaginationMapperProxy proxy = new PaginationMapperProxy(sqlSession); return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy); } }
PaginationMapperMethod
public class PaginationMapperMethod { private SqlSession sqlSession; private Configuration config; private SqlCommandType type; private String commandName; private String commandCountName; private Class<?> declaringInterface; private Method method; private Integer rowBoundsIndex; private Integer paginationIndex; private List<String> paramNames; private List<Integer> paramPositions; private boolean hasNamedParameters; public PaginationMapperMethod(Class<?> declaringInterface, Method method, SqlSession sqlSession) { paramNames = new ArrayList<String>(); paramPositions = new ArrayList<Integer>(); this.sqlSession = sqlSession; this.method = method; this.config = sqlSession.getConfiguration(); this.hasNamedParameters = false; this.declaringInterface = declaringInterface; setupFields(); setupMethodSignature(); setupCommandType(); validateStatement(); } @SuppressWarnings({ "unchecked", "rawtypes" }) public Object execute(Object[] args) { final Object param = getParam(args); Pagination<Object> page; RowBounds rowBounds; if (paginationIndex != null) { page = (Pagination) args[paginationIndex]; rowBounds = page.newRowBounds(); } else if (rowBoundsIndex != null) { rowBounds = (RowBounds) args[rowBoundsIndex]; page = new Pagination<Object>(rowBounds); } else { throw new BindingException("Invalid bound statement (not found rowBounds or pagination in paramenters)"); } page.setTotal(executeForCount(param)); page.setList(executeForList(param, rowBounds)); return page; } private long executeForCount(Object param) { Number result = (Number) sqlSession.selectOne(commandCountName, param); return result.longValue(); } @SuppressWarnings("rawtypes") private List executeForList(Object param, RowBounds rowBounds) { return sqlSession.selectList(commandName, param, rowBounds); } private Object getParam(Object[] args) { final int paramCount = paramPositions.size(); if (args == null || paramCount == 0) { return null; } else if (!hasNamedParameters && paramCount == 1) { return args[paramPositions.get(0)]; } else { Map<String, Object> param = new HashMap<String, Object>(); for (int i = 0; i < paramCount; i++) { param.put(paramNames.get(i), args[paramPositions.get(i)]); } return param; } } private void setupMethodSignature() { final Class<?>[] argTypes = method.getParameterTypes(); for (int i = 0; i < argTypes.length; i++) { if (Pagination.class.isAssignableFrom(argTypes[i])) { paginationIndex = i; } else if (RowBounds.class.isAssignableFrom(argTypes[i])) { rowBoundsIndex = i; } else { String paramName = String.valueOf(paramPositions.size()); paramName = getParamNameFromAnnotation(i, paramName); paramNames.add(paramName); paramPositions.add(i); } } } private String getParamNameFromAnnotation(int i, String paramName) { Object[] paramAnnos = method.getParameterAnnotations()[i]; for (Object paramAnno : paramAnnos) { if (paramAnno instanceof Param) { hasNamedParameters = true; paramName = ((Param) paramAnno).value(); } } return paramName; } private void setupFields() { commandName = declaringInterface.getName() + "." + method.getName(); commandCountName = commandName + "Count"; // 命名约定 } private void setupCommandType() { MappedStatement ms = config.getMappedStatement(commandName); type = ms.getSqlCommandType(); if (type != SqlCommandType.SELECT) { throw new BindingException("Unsupport execution method for: " + commandName); } } private void validateStatement() { if (!config.hasStatement(commandName)) { throw new BindingException("Invalid bound statement (not found): " + commandName); } if (!config.hasStatement(commandCountName)) { throw new BindingException("Invalid bound statement (not found): " + commandCountName); } } }
具体某个查询的SQL配置
<select id="findAll" resultMap="helloResultMap"> select * from HELLO </select> <select id="findAllCount" resultType="long"> select count(*) from HELLO </select>
补代码Pagination,分页辅助类
public class Pagination<T> { private long total; private int pagesize; private List<T> list = Collections.emptyList(); private int offset; private int limit; private int page; public Pagination() { this(1, 15); } public Pagination(int page) { this(page, 15); } public Pagination(int page, int limit) { setPage(page); setLimit(limit); } public Pagination(RowBounds rowBounds) { this.limit = rowBounds.getLimit(); this.offset = rowBounds.getOffset(); this.page = offset / limit + 1; } public void setPage(int page) { if (page < 0) { page = 1; } this.page = page; onInit(); } public void setLimit(int limit) { if (limit < 1) { limit = 15; } this.limit = limit; onInit(); } protected void onInit() { offset = (page - 1) * limit; } protected void onSetRowsize() { pagesize = (int) (total / limit); if (total % limit > 0) { pagesize ++; } if (page > pagesize) { page = pagesize; onInit(); } } protected void onSetList() { if (list == null || list.isEmpty()) { total = 0; page = 1; offset = 0; } } public long getTotal() { return total; } public void setTotal(long rowsize) { this.total = rowsize; onSetRowsize(); } public int getPagesize() { return pagesize; } public List<T> getList() { return list; } public void setList(List<T> list) { this.list = list; onSetList(); } public int getOffset() { return offset; } public int getLimit() { return limit; } public int getPage() { return page; } public RowBounds newRowBounds() { return new RowBounds(getOffset(), getLimit()); } }
目前无可避免的需要两段sql。在考虑如何实现自动生成count(*),但目前做到这样,已经达到自己的预期了。暂时先就这样吧!
评论
8 楼
张飞1
2016-01-11
你好!,看了你这篇文章,然后阅读了一下源码,在XMLConfigBuilder中直接使用的new Configuration,我使用的是spring,我想问一下这个怎么能够调用自己的Configuration
7 楼
anglny
2013-05-24
你定义一个所有实体对象的父实体。然后在里面定义一个total的变量。在你做分页操作的时候查一次count(*) 然后把值set进父实体。
6 楼
icefire
2013-05-13
clxy 写道
我也在找这个实现。你这里的方法有些“繁琐”,需要动太多mybatis的类了。
在https://github.com/yfyang/mybatis-pagination这里看到个实现,其他部分优劣不说,
只是觉得自动执行取总数部分还是可以借鉴的。
也供你参考。
在https://github.com/yfyang/mybatis-pagination这里看到个实现,其他部分优劣不说,
只是觉得自动执行取总数部分还是可以借鉴的。
也供你参考。
粗略看了下,你提供的这个应该会好些,比较适合用到项目中。我这个就自己业余写的demo,实际项目使用还差得多。自己工作也没使用mybatis,也就没继续深入了。
5 楼
clxy
2013-05-09
我也在找这个实现。你这里的方法有些“繁琐”,需要动太多mybatis的类了。
在https://github.com/yfyang/mybatis-pagination这里看到个实现,其他部分优劣不说,
只是觉得自动执行取总数部分还是可以借鉴的。
也供你参考。
在https://github.com/yfyang/mybatis-pagination这里看到个实现,其他部分优劣不说,
只是觉得自动执行取总数部分还是可以借鉴的。
也供你参考。
4 楼
mygia
2012-08-23
学习一下!
3 楼
icefire
2011-11-29
kelor 写道
看了下源代码,在创建sessionFactory,session对象的时候传入的参数都是Configuration。
如果要用自己的Configuration。是不是也要扩展下XMLConfigBuilder,使用自定义的Configuration来初始化configuration属性?
如果要用自己的Configuration。是不是也要扩展下XMLConfigBuilder,使用自定义的Configuration来初始化configuration属性?
不知道你的需求是怎样的,如果用spring,就没必要用xml来初始化Configuration了。如果是xml要增加自己的属性,可能需要扩展XMLConfigBuilder吧,具体没研究过了。我使用自己的Configuration是因为我要替换其中的属性,Configuration又没提供set方法,所以别无选择。
2 楼
kelor
2011-11-25
看了下源代码,在创建sessionFactory,session对象的时候传入的参数都是Configuration。
如果要用自己的Configuration。是不是也要扩展下XMLConfigBuilder,使用自定义的Configuration来初始化configuration属性?
如果要用自己的Configuration。是不是也要扩展下XMLConfigBuilder,使用自定义的Configuration来初始化configuration属性?
1 楼
guoyi_20082008
2011-10-14
也按照此方式实现,但发现缺少Pagination类的代码,不知能否附上,谢谢
发表评论
-
mybatis分页实现1
2011-05-05 00:07 14948最近开始尝试用mybatis,比较郁闷其对分页的实现,看了网上 ... -
有关REST
2010-09-15 12:50 1295关注REST说起来,应该是 ... -
阶段小结
2007-08-17 11:16 1548前段时间忙这敢着做东 ... -
taglib
2007-06-18 09:32 2092昨天居然让我碰上自己写的JSP标签没法加载的问题,真叫一个郁闷 ... -
struts的资源文件配置
2007-05-22 15:08 2918xml 代码 <message-reso ... -
模仿写组件
2007-05-17 14:01 1594第一次在JavaEye上写BLOG ...
相关推荐
06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo...
一个集成spring的MyBatis的分页功能实现的例子
自己封装的mybatis分页jar包,实现了mybatis的物理分页,目前只支持mysql和oracle两种数据库。
springboot集成mybatis分页插件的一个小demo,用xml实现sql语句
工具类flume官方jar包,工具类flume官方jar包,工具类flume官方jar包,工具类flume官方jar包,
本链接主要为MyBatis使用分页插件实现分页所需Jar包
一、引言Mybatis提供了强大的分页拦截实现,可以完美的实现分功能二、普通的分页实现普通分页实现即使直接在mapper文件中写分页查询语句Messsage.x
本人博客中的代码Jsp+Servlet+MyBatis完成分页查询 http://blog.csdn.net/japanstudylang/article/details/51700874
MyBatis自动分页实现 不用自己写代码
mybatis分页查询例子 idea实现, 分页查询,员工工资。
Mybatis PageHelper(Mybatis分页插件) v5.0 最新免费版.rar
mybatis分页共享,本资源基于插件机制,通过拦截StatementHandler重写sql语句,实现数据库的物理分页。基于mybatis3.2.2开发,使用时注意版本。
<!-- 分页配置--> <bean id="pagePlugin" class="com.qc.dframework.mybatis.PageInterceptor"> <prop key="databaseType">mysql </bean>
mybatis分页的配置方法,可以实现物理分页
mybatis 分页代码 基于内存分页 有需要的同学看看吧
mybatis 分页插件 PageHelper5.0.0 mybatis 最简单的方式实现物理分页
spring+mybatis实现了物理分页的
利用自定义jstl标签,实现mybatis分页查询
自己最近搭建的一个SpringMVC+Mybatis的框架 属于无实体类的框架 ... 并实现了Myabtis的自动分页和总数查询 只要传入分页参数便能自动查询总数和分页 总数封装在参数里面执行查询后可以直接从参数中获取