`
iorn.gu
  • 浏览: 3257 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

基于spring与hibernate的通用分页实现

阅读更多
最近做了个分页..  拿出来大家讨论一下.

先看一下效果.
在HTML代码:
js框架用的是jQuery. table函数是我自己做的一个表格插件.
<#import "/spring.ftl" as spring/>
<#import "/shop.ftl" as shop/>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  	<title>Data Table Demo</title>
  </head>

  <body>
  	<script>
  		$(function(){
  			$('.table4').table({
  				headers : ['<@spring.message code="profile.detail.title"/>'],
  				data_columns : ['name'],
  				data_key: 'data',
  				data_url : $.root_ctx + '/demo/table3.htm',
  				pageable: true,
  				ajaxPager: true,
  				pageSize: 6
  			});
  			
  		});
  	</script>
  	<div style="width: 90%">
  	<@shop.panel height=245>
  		<table class="table4" border="0" cellspacing="0" cellpadding="0"></table>
  	</@shop.panel>
  	</div>
  </body>
</html>



再看controller里.
@Controller
public class DemoController extends BaseController{
	
	private ShopService shopService = null;
	
	@Autowired
	public void setShopService(ShopService shopService) {
		this.shopService = shopService;
	}

	@RequestMapping("/demo/table3.htm")
	public String testTable3(HttpServletRequest request,ModelMap map) {
		Object o = doPage(request, map, new PagerExecutor() {
			@Override
			public List<?> doInPager(Pager pager) {
				return shopService.list();
			}
		});
		map.addAttribute("data", escapeForJson(o));
		return JSON;
	}
}


service里的list方法实现
	@Override
	//@Exclude("BaseDao.list")
	public List<Shop> list() {
		return shopDao.list();
	}



dao里的list方法实现
	@SuppressWarnings("unchecked")
	@Override
	public List<T> list() throws DataAccessException {
		return getHibernateTemplate().loadAll(clazz);
	}


到现在. 分页相关的代码已经写完了.
可以看到. service与dao里没有任何与分页有关的代码.
接下来看下实现分页相关的东西.



Pager接口
/**
 * @author Iorn.Gu
 */
public interface Pager {

	boolean isEnabled();
	
	void setPageSize(int pageSize);
	int getPageSize();
	
	void setCurrentPage(int currentPage);
	int getCurrentPage();
	
	void setFetchCount(boolean fetchCount);
	
	PagerResult execute(PagerExecutor executor);
}



实现类
public class PagerImpl implements Pager{

	private boolean enabled = false;
	private boolean fetchCount = false;
	private int pageSize = 10;
	private int currentPage = 0;
	
	private static final Object LOCK = new Object();
	
	@Override
	public PagerResult execute(PagerExecutor executor) {
		synchronized (LOCK) {
			PagerResult result = new PagerResult();
			if( fetchCount || currentPage < 0) {
				enabled = false;
				List<?> re = executor.doInPager(this);
				result.setItemCount(re.size());
				fetchCount = false;
			} else if( currentPage != 0 ){
				enabled = true;
				List<?> re = executor.doInPager(this);
				result.setPageItems(re);
				enabled = false;
			}
			currentPage = 0;
			return result;
		}
	}

	@Override
	public void setCurrentPage(int currentPage) {
		synchronized (LOCK) {
			if( !isEnabled() )
				this.currentPage = currentPage;
		}
	}

	@Override
	public void setPageSize(int pageSize) {
		synchronized (LOCK) {
			if( !isEnabled() )
				this.pageSize = pageSize;
		}
	}

	@Override
	public int getCurrentPage() {
		return currentPage;
	}

	@Override
	public int getPageSize() {
		return pageSize;
	}

	@Override
	public boolean isEnabled() {
		return enabled;
	}

	public void setFetchCount(boolean fetchCount) {
		this.fetchCount = fetchCount;
	}
	
}


PagerResult
public class PagerResult {

	private int itemCount = 0;
	private List<?> pageItems = null;
	
	public int getItemCount() {
		return itemCount;
	}
	
	public void setItemCount(int itemCount) {
		this.itemCount = itemCount;
	}
	
	public List<?> getPageItems() {
		return pageItems;
	}
	
	public void setPageItems(List<?> pageItems) {
		this.pageItems = pageItems;
	}
	
}


PagerExecutor
public interface PagerExecutor {

	List<?> doInPager(Pager pager);
	
}


PageableHibernateTemplete类.
关于PagerMethodExcludeHolder 这个类相关的东西.到最后再说吧.先忽略.! 只看两个prepare方法.
public class PageableHibernateTemplete extends HibernateTemplate {

	private Pager pager = null;
	private PagerMethodExcludeHolder excludeHolder = null;
	
	public PageableHibernateTemplete(SessionFactory sessionFactory) {
		super(sessionFactory);
	}
	
	@Autowired
	public void setPager(Pager pager) {
		this.pager = pager;
	}

	@Autowired
	public void setExcludeHolder(PagerMethodExcludeHolder excludeHolder) {
		this.excludeHolder = excludeHolder;
	}

	@Override
	protected void prepareCriteria(Criteria criteria) {
		if( pager.isEnabled() && !isMethodExcluded()) {
			criteria.setFirstResult((pager.getCurrentPage()-1)*pager.getPageSize());
			setMaxResults(pager.getPageSize());
		} else {
			criteria.setFirstResult(0);
			setMaxResults(0);
		}
		super.prepareCriteria(criteria);
	}

	@Override
	protected void prepareQuery(Query queryObject) {
		if( pager.isEnabled() && !isMethodExcluded() ) {
			queryObject.setFirstResult((pager.getCurrentPage()-1)*pager.getPageSize());
			setMaxResults(pager.getPageSize());
		} else {
			queryObject.setFirstResult(0);
			setMaxResults(0);
		}
		super.prepareQuery(queryObject);
	}
	
	private boolean isMethodExcluded() {
		String[] excludeds = excludeHolder.getExcludeMethods();
		if( excludeds != null ) {
			StackTraceElement[] elements = (new Throwable()).getStackTrace();
			boolean inDao = false;
			for( StackTraceElement element : elements ) {
				if( element.getClassName().endsWith("DaoImpl") ) {
					inDao = true;
					for( String excluded : excludeds ) {
						String method = excluded.substring(excluded.lastIndexOf(".")+1);
						String prefix = excluded.substring(0,excluded.lastIndexOf("."));
						if( element.getMethodName().equals(method) && element.getClassName().indexOf(prefix) != -1 ) {
							System.out.println("exlucde Method:" + element.getClassName() + "." + element.getMethodName());
							return true;
						}
					}
				} else if( inDao ){
					break;
				}
			}
		}
		return false;
	}
	
}


然后是BaseController类的doPager(在上面的controller那块里头用到)方法.
	@SuppressWarnings("unchecked")
	protected List<?> doPage(HttpServletRequest request,Map model,PagerExecutor executor) {
		String getItemCount = request.getParameter("getItemCount");
		String currentPage = request.getParameter("currentPage");
		String pageSize = request.getParameter("pageSize");
		
		if( "true".equals(getItemCount) ) {
			pager.setFetchCount(true);
			PagerResult result = pager.execute(executor);
			model.put("itemCount", result.getItemCount());
			return null;
		} else if( currentPage != null && !"".equals(currentPage) ) {
			int curr = Integer.parseInt(currentPage);
			pager.setCurrentPage(curr);
			if( pageSize != null && !"".equals(pageSize) ) {
				int ps = Integer.parseInt(pageSize);
				pager.setPageSize(ps);
			}
		} else {
			pager.setCurrentPage(-1);
		}
		PagerResult result = pager.execute(executor);
		
		return result.getPageItems();
	}


最后就是那个jQuery的table插件了.. 代码太长. 就只贴取数据那一段了.
var AjaxPageableDataModel = function(config){
		var param = $.extend({},config.data_param);
		$.extend(param,{'getItemCount':true});
		
		$.ajax({
			async : false,
			url : config.data_url,
			data : param,
			type : 'POST',
			cache : true,
			success : function(data){
				config.itemCount = eval('('+data+')').itemCount;
			}
		});
		param['getItemCount'] = false;
		
		config.pageCount = parseInt(config.itemCount / config.pageSize);
		config.pageCount += ((config.itemCount % config.pageSize == 0) ? 0 : 1)
		
		return {
			getData : function(curPage){
				config.currentPage = curPage ? curPage : 1;
				param['currentPage'] = config.currentPage;
				param['pageSize'] = config.pageSize;
				
				var result = false;
				$.ajax({
					async : false,
					url : config.data_url,
					data : param,
					type : 'POST',
					success : function(data){
						result = eval('('+data+')');
					}
				});
				return (result && result[config.data_key]) ? result[config.data_key] : [];
			},
			getPageCount : function(){
				return config.pageCount;
			},
			getItemCount : function(){
				return config.itemCount;
			}
		}
	};


就这些了. 虽然没写注释,但应该不难看懂.

然后还有PagerMethodExcludeHolder类没有贴.. 这个要说明一下.
因为在service层的方法里. 有可能会调用多个dao的方法. 而dao的方法并不是每一个都要分页处理. 这时就要用到这个类相关的东西了.
在上面的service方法里. 注释了一行@Exclude("BaseDao.list"). 这行表示.BaseDao里的list方法不需要做分页处理.
下面是这些东西的代码.

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Exclude {

	String[] value() default {};
	
}



@Aspect
public class PagerMethodExcludeHolder {

	private Map<Method, String[]> methodCache = new HashMap<Method, String[]>();
	private String[] excludeMethods = null;
	
	@Around("execution(public java.util.List *..*service..*.*(..)) and @annotation(com.guyong.common.pager.Exclude)")
	public Object whenPager(ProceedingJoinPoint joinPoint) throws Throwable {
		Method method = getCurrentMethod(joinPoint);
		if( !methodCache.containsKey(method) ) {
			Exclude exclude = AnnotationUtils.findAnnotation(method, Exclude.class);
			String[] excludes = null;
			if( exclude != null ) {
				excludes = exclude.value();
			}
			methodCache.put(method, excludes);
		}
		excludeMethods = methodCache.get(method);
		Object result = joinPoint.proceed();
		excludeMethods = null;
		return result;
	}
	
	private Method getCurrentMethod(ProceedingJoinPoint joinPoint) {
		Signature s = joinPoint.getSignature();
		Class<?> clazz = joinPoint.getTarget().getClass();
		Method getMethod = ReflectionUtils.findMethod(s.getClass(), "getMethod");
		ReflectionUtils.makeAccessible(getMethod);
		Method tmp = (Method)ReflectionUtils.invokeMethod(getMethod, s);
		Class<?>[] argTypes = tmp.getParameterTypes();
		return ReflectionUtils.findMethod(clazz, s.getName(), argTypes);
	}

	public String[] getExcludeMethods() {
		return excludeMethods;
	}
	
}



好了..  欢迎大家批评指教.
附件里是效果图跟每页数据的返回值..
  • 大小: 31.1 KB
分享到:
评论
37 楼 kjj 2008-12-24  
我看了楼主的代码,设计模式用得不少,看看是否太复杂了

我也来show 一下我的分页小例子,实现了底层对table 和导航页码的封装,不过没有打包,大家可以去svn下下载源代码,原来觉得页面使用tag是很繁琐的事情,因此就自己实现了底层,在action中调用时直接用java生成html,也页面配合好css 控制样式,后来发现tag是最好的方式,因为还有许多配置需要用户自定义来实现,比如对某个列的renderer,列数目,用api ,十分不方便了

简单说明,google的wiki 样式不好控制
http://code.google.com/p/javaman/wiki/GettingStarted
下载
http://code.google.com/p/javaman/downloads/list
source
http://code.google.com/p/javaman/source/checkout
36 楼 karneq 2008-10-20  
Java在Web开发语言上败给了PHP
35 楼 hyys2008 2008-10-13  
jacklondon 写道
hyys2008 写道
jacklondon 写道
hyys2008 写道
daquan198163 写道
jacklondon 写道
daquan198163 写道
看了此贴,我对实现通用分页这件事彻底绝望了

我写了一个通用分页,应该比这里的简单。可供参考。
http://blog.csdn.net/jacklondon/archive/2008/08/23/2816824.aspx
这是一个开源 J2EE 框架项目 VelocityWeb,主页在 http://velocityweb.sourceforge.net, 有中英文文档。
加入分页功能是因为一个网友的要求。

简单看了一下你的blog,好像是个SQL级别的分页组件,跟Hibernate的QBC类似,
这跟我们在这里讨论的通用分页框架不是一码事吧,
这里讨论的是比较高层的框架,不限制你在底层用JDBC还是ORM,
而你那个属于底层的分页组件



最讨厌这种质量低下的框架。用了就完蛋了,真浪费sourceforge的空间

顺便问一句,你用过 VelocityWeb 么?没有用过怎么知道好坏?
至少我认为 VelocityWeb 中的分页,比 Javaeye 论坛中出现的绝大部分分页,要强很多。



但是,偶用过spring啊,他的代码写的很漂亮,质量很搞,我很乐意用,我看了一下,你的cvs目录结构好像都不太符合好的版本目录结构,还有,没有一个完整的构建系统,有个ant都还好的多,连构建系统都没有,很先测试也没有了,因此,偶估计代码质量应该高不到哪儿去,你觉得我说的对不对?

spring的代码,偶读起来就像读一片英文文章一样,像看小说一样,很轻松的读完,可是,我想读你那个框架代码应该没有这样的感觉吧?

 

不要生气,偶只是说说我的想法,哈哈,开开玩笑,偶每天写代码,那些代码也是狂浪费偶的硬盘空间呢,哥哥不要在意嘛。哈哈

首先,偶很鄙视 Spring, 也鄙视用 Spring 的人。
其次,偶的分页程序,是在 Hibernate/phpbb 分页程序基础上开发的,修正了这两个大名鼎鼎的开源项目分页不支持 order by/distinct/group by 的 bug.
再其次,目录结构问题,随你怎么说吧。我自认为没有问题。
最后,Ant 问题。VelocityWeb 及其 sample petstore 都有 build.xml. 我不知道你所谓的"连构建系统都没有"是什么意思?



Oh, My Gode,Don't anger,I am just say ,just so so.
34 楼 hyys2008 2008-10-13  
现在这个年头,开源真多哦,连一个分页都有这么多开源的,我的天,我要学到什么实惠哦哦,了不得了.
33 楼 hyys2008 2008-10-13  
看来你们两个小兄弟要PK你们的分页框架了哦,不要伤及无辜偶哦,嘿嘿
32 楼 hyys2008 2008-10-13  
daquan198163 写道
哦,也包括我这个吗?http://www.iteye.com/topic/24772
而且前面我也说过了,我们这里讨论的是比较高层的框架,不限制底层用JDBC还是ORM,
而你那个属于底层的分页组件,
Javaeye 论坛中出现的绝大部分分页都是都是我说的那个层次的,
所以你说你的那个比谁强就有点莫名其妙了

ps:你能说说你的那个比Hibernate QBC强在哪儿吗?

hyys2008的无理取闹可以无视


大侠,你看看我上面说的有没有道理? 
31 楼 hyys2008 2008-10-13  
jacklondon 写道
hyys2008 写道
daquan198163 写道
jacklondon 写道
daquan198163 写道
看了此贴,我对实现通用分页这件事彻底绝望了

我写了一个通用分页,应该比这里的简单。可供参考。
http://blog.csdn.net/jacklondon/archive/2008/08/23/2816824.aspx
这是一个开源 J2EE 框架项目 VelocityWeb,主页在 http://velocityweb.sourceforge.net, 有中英文文档。
加入分页功能是因为一个网友的要求。

简单看了一下你的blog,好像是个SQL级别的分页组件,跟Hibernate的QBC类似,
这跟我们在这里讨论的通用分页框架不是一码事吧,
这里讨论的是比较高层的框架,不限制你在底层用JDBC还是ORM,
而你那个属于底层的分页组件



最讨厌这种质量低下的框架。用了就完蛋了,真浪费sourceforge的空间

顺便问一句,你用过 VelocityWeb 么?没有用过怎么知道好坏?
至少我认为 VelocityWeb 中的分页,比 Javaeye 论坛中出现的绝大部分分页,要强很多。



但是,偶用过spring啊,他的代码写的很漂亮,质量很搞,我很乐意用,我看了一下,你的cvs目录结构好像都不太符合好的版本目录结构,还有,没有一个完整的构建系统,有个ant都还好的多,连构建系统都没有,很先测试也没有了,因此,偶估计代码质量应该高不到哪儿去,你觉得我说的对不对?

spring的代码,偶读起来就像读一片英文文章一样,像看小说一样,很轻松的读完,可是,我想读你那个框架代码应该没有这样的感觉吧?

 

不要生气,偶只是说说我的想法,哈哈,开开玩笑,偶每天写代码,那些代码也是狂浪费偶的硬盘空间呢,哥哥不要在意嘛。哈哈
30 楼 daquan198163 2008-10-12  
哦,也包括我这个吗?http://www.iteye.com/topic/24772
而且前面我也说过了,我们这里讨论的是比较高层的框架,不限制底层用JDBC还是ORM,
而你那个属于底层的分页组件,
Javaeye 论坛中出现的绝大部分分页都是都是我说的那个层次的,
所以你说你的那个比谁强就有点莫名其妙了

ps:你能说说你的那个比Hibernate QBC强在哪儿吗?

hyys2008的无理取闹可以无视
29 楼 hyys2008 2008-10-12  
daquan198163 写道
jacklondon 写道
daquan198163 写道
看了此贴,我对实现通用分页这件事彻底绝望了

我写了一个通用分页,应该比这里的简单。可供参考。
http://blog.csdn.net/jacklondon/archive/2008/08/23/2816824.aspx
这是一个开源 J2EE 框架项目 VelocityWeb,主页在 http://velocityweb.sourceforge.net, 有中英文文档。
加入分页功能是因为一个网友的要求。

简单看了一下你的blog,好像是个SQL级别的分页组件,跟Hibernate的QBC类似,
这跟我们在这里讨论的通用分页框架不是一码事吧,
这里讨论的是比较高层的框架,不限制你在底层用JDBC还是ORM,
而你那个属于底层的分页组件



最讨厌这种质量低下的框架。用了就完蛋了,真浪费sourceforge的空间
28 楼 iampurse 2008-10-11  
- - 。 算我说错话。

不过真是有够诡异的这 。

想要分页的话 Google PageHibernateTemplate.jave就有现成代码
27 楼 iampurse 2008-10-11  
其实楼主代码里头已经有了分页模块

就是那个PageHibernateTemplate 。

大家要用的话就用那个就好勒。

把参数传进去就能获得到特定页的record。

至于剩下的都是数据传输啦 - -~
26 楼 myyate 2008-10-10  
问一下,如果是有很多查询参数,查询了以后再分页,参数如何保存的?你这个分页对不需要查询的显示倒是可以。
还有,你的页面tag具体如何实现的?
我在公司里做了一个,就3个class就可以了,我个人感觉你把简单问题复杂化了。
25 楼 chenkan2000 2008-10-10  
想要知道共有多少条记录符合条件,怎么办?你的分页里好像没有这个功能。

需要的JDK版本太高了,许多项目都用1.4。
24 楼 andy54321 2008-10-09  
这个分页也太繁琐了吧。。。。。

通用分野,提供对外几个接口,三下两下一配置,搞定,就好了

23 楼 lirig 2008-10-09  
daquan198163 写道
jacklondon 写道
daquan198163 写道
看了此贴,我对实现通用分页这件事彻底绝望了

我写了一个通用分页,应该比这里的简单。可供参考。
http://blog.csdn.net/jacklondon/archive/2008/08/23/2816824.aspx
这是一个开源 J2EE 框架项目 VelocityWeb,主页在 http://velocityweb.sourceforge.net, 有中英文文档。
加入分页功能是因为一个网友的要求。

简单看了一下你的blog,好像是个SQL级别的分页组件,跟Hibernate的QBC类似,
这跟我们在这里讨论的通用分页框架不是一码事吧,
这里讨论的是比较高层的框架,不限制你在底层用JDBC还是ORM,
而你那个属于底层的分页组件


分页根本就没有什么框架,只要设计合理,性能好,调用方便就可以了,分页只是一个比较普遍而且简单的功能,用不着那么复杂!
22 楼 lirig 2008-10-09  
过于复杂!一个分页不用那么麻烦!
21 楼 thinkintime 2008-10-09  
老弟,换成mysql,sql server,oracle,sysbase....都能通用吗?分页效率如何?达到这些要求才能算是一个好的通用分页,至于在表现层应该很多比你写的简单
20 楼 showtime520 2008-10-07  
还是用pagerTaglib
19 楼 jieyuan_cg 2008-10-07  
PageableHibernateTemplete 里面的 Paper类是什么时候注册进来的?能动态改变?
18 楼 kenvin 2008-10-07  
没有什么所谓的通用的分页框架,通用的分页只能局限在一个特定的项目里,与项目所采用的各种开源框架关系密切。查询分页本来就是一个繁琐的问题,它包括组织查询的过滤条件和查询结果的排序等等需要考虑的问题。

相关推荐

    Struts+Spring+Hibernate通用分页解决方案

    "Struts+Spring+Hibernate通用分页解决方案"是针对基于这三大框架(Struts、Spring、Hibernate)的Java Web应用所设计的一种高效且可复用的分页策略。以下是关于这个主题的详细解释: 1. **Struts框架**:Struts是...

    struts+spring+hibernate通用分页方法

    struts+spring+hibernate通用分页方法.rar 博文链接:https://igogogo9.iteye.com/blog/97692

    Spring+Hibernate完整分页

    本文将深入探讨如何利用Spring和Hibernate实现完整的分页功能,并结合MySQL数据库进行操作。 首先,Spring是一个轻量级的框架,它提供了全面的DI服务,允许开发者通过XML配置或注解来管理对象的生命周期和依赖关系...

    Struts2 Spring3 Hibernate 注解功能 DAO 泛型 通用分页

    此外,通用分页是Web应用中常见的需求,可以使用Spring JPA的`Pageable`接口或者自定义分页查询方法来实现。通过传递页码和每页大小,可以轻松获取数据的指定部分,同时获取总页数等信息,提升用户浏览大量数据时的...

    Hibernate+Struts+Spring 实现的通用分页查询

    总结来说,使用Hibernate、Struts和Spring实现的通用分页查询,涉及了Java Web开发中的多个层次,包括模型、持久层接口、持久层实现、业务层和服务层的交互,以及视图层的渲染。这种分页机制灵活且可复用,可以适应...

    Spring/泛型Hibernate的实现

    ### 泛型Hibernate的实现与Spring集成 #### 一、泛型Hibernate概念及其实现 在Java开发领域,尤其在企业级应用开发中,Hibernate框架因其强大的对象关系映射(ORM)能力而受到广泛欢迎。泛型Hibernate是利用Java...

    spring-hibernate分页

    该文档提供了两种分页方法:其中一种是hibernate提供的原始分页方法,另一种是自己封装的使用于 spring hibernate 的通用分页方法。如有不妥,欢迎指正 !

    spring和hibernate集成后,通用的basedao

    在这个名为"ssh"的压缩包中,很可能包含了一个关于Spring和Hibernate集成的示例代码,用于实现一个通用的基于DAO(Data Access Object)的设计模式。 Spring框架通过其IoC(Inversion of Control,控制反转)和AOP...

    hibernate sturts 分页 通用

    在IT行业中,分页是网页...这些代码应该展示了如何在Hibernate和Struts基础上实现通用的分页功能,并可能通过Spring进行优化。通过学习和理解这些代码,开发者可以掌握如何在实际项目中实现高效且可复用的分页机制。

    基于hibernate 通用查询框架,包含查询、分页列表 功能

    通用查询页面中的查询项、查询出的分页列表都是自动生成的。开发简便、快速,附件中是一套完整的demo和使用说明 支持全部Hql语法格式 Awake 后续功能扩展 1.XML格式数据输出,保证了ajax用户也可以使用Awake框架...

    第24次课-1 Spring与Hibernate的整合

    第24次课-1 Spring与Hibernate的整合 本节主要内容 24.1 概述 24.2 管理SessionFactory 24.3 Spring对Hibernate的简化 24.1 概述 24.1.1 概述 Spring提供了很多IoC特性的支持,方便处理大部分典型的Hibernate整合...

Global site tag (gtag.js) - Google Analytics