spring+hibernate+struts2 annotation兑现分页(1)

spring+hibernate+struts2 annotation实现分页(1)
这几天写了个ssh2分页实现,放到博客里留个记号,先贴代码有空再写说明了
@Entity(name="t_person")
public class Person implements Serializable {

	private static final long serialVersionUID = 1L;
	@Id
    @GeneratedValue(strategy=GenerationType.AUTO)
	private int id;
	
	@Column(length=50,name="p_name")
	private String name;
	
	@Column(name="p_sex",nullable=true)
	private String sex;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}
}


package com.xangqun.base;

import java.io.Serializable;
import java.util.concurrent.locks.Condition;

import com.xangqun.page.OrderBy;
import com.xangqun.page.Pagination;



public interface BaseDao <T extends Serializable>{

	/**
	 * 
	 * @param eg 示例对象
	 * @param anyWhere 是否模糊查询,默认false。
	 * @param conds 排序和is null的字段。分别为OrderBy和String。
	 * @param pageNo 当前页号
	 * @param pageSize 每页记录数
	 * @param exclude 需要排除的属性
	 * @return
	 * @throws Exception 
	 */
	public Pagination find(T eg, boolean anyWhere,
			Condition[] conds, int pageNo, int pageSize, String... exclude) ;
	
	public Pagination findAll(int pageNo, int pageSize, OrderBy... orders);
}

package com.xangqun.base;

import static org.hibernate.EntityMode.POJO;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Example.PropertySelector;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.Type;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import com.xangqun.page.Nullable;
import com.xangqun.page.OrderBy;
import com.xangqun.page.Pagination;

@Transactional
public abstract class BaseDaoImpl<T extends Serializable>  implements BaseDao<T> {

	public static final NotBlankPropertySelector NOT_BLANK = new NotBlankPropertySelector();

	private Class<T> persistentClass;

	protected SessionFactory sessionFactory;
	

	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}


	@SuppressWarnings("unchecked")
	public BaseDaoImpl() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	/**
	 * 
	 * @param eg 示例对象
	 * @param anyWhere 是否模糊查询,默认false。
	 * @param conds 排序和is null的字段。分别为OrderBy和String。
	 * @param pageNo 当前页号
	 * @param pageSize 每页记录数
	 * @param exclude 需要排除的属性
	 * @return
	 */
	@Override
	@Transactional(isolation=Isolation.DEFAULT,readOnly=true)
	public Pagination find(T eg, boolean anyWhere, Condition[] conds,
			int pageNo, int pageSize, String... exclude) {
		Order[] orderArr=null;
		Condition[] condArr=null;
		if (conds != null && conds.length > 0) {
			List<Order> orderList = new ArrayList<Order>();
			List<Condition> condList = new ArrayList<Condition>();
			for (Condition c : conds) {
				if (c instanceof OrderBy) {
					orderList.add(((OrderBy) c).getOrder());
				} else {
					condList.add(c);
				}
			}
			orderArr = new Order[orderList.size()];
			condArr = new Condition[condList.size()];
			orderArr = orderList.toArray(orderArr);
			condArr = condList.toArray(condArr);
		}
		Criteria crit = getCritByEg(eg, anyWhere, condArr, exclude);
		return findByCriteria(crit, pageNo, pageSize, null, orderArr);
	}

	@SuppressWarnings("unchecked")
	protected ClassMetadata getCmd(Class clazz) {
		return (ClassMetadata) getSessionFactory().getClassMetadata(clazz);
	}
	@Transactional(isolation=Isolation.DEFAULT,readOnly=true)
	protected Criteria getCritByEg(T eg, boolean anyWhere, Condition[] conds,
			String[] exclude) {
		System.out.println(getSession().isOpen());
		Criteria crit = getSession().createCriteria(getPersistentClass());
		Example example = Example.create(eg);
		System.out.println(eg);
		example.setPropertySelector(NOT_BLANK);
		if (anyWhere) {
			example.enableLike(MatchMode.ANYWHERE);
			example.ignoreCase();
		}
		for (String p : exclude) {
			example.excludeProperty(p);
		}
		crit.add(example);
		// 处理排序和is null字段
		if (conds != null) {
			for (Condition o : conds) {
				if (o instanceof OrderBy) {
					OrderBy order = (OrderBy) o;
					crit.addOrder(order.getOrder());
				} else if (o instanceof Nullable) {
					Nullable isNull = (Nullable) o;
					if (isNull.isNull()) {
						crit.add(Restrictions.isNull(isNull.getField()));
					} else {
						crit.add(Restrictions.isNotNull(isNull.getField()));
					}
				} else {
					// never
				}
			}
		}
		// 处理many to one查询
		ClassMetadata cm = getCmd(eg.getClass());
		String[] fieldNames = cm.getPropertyNames();
		for (String field : fieldNames) {
			Object o = cm.getPropertyValue(eg, field, POJO);
			if (o == null) {
				continue;
			}
			ClassMetadata subCm = getCmd(o.getClass());
			if (subCm == null) {
				continue;
			}
			Serializable id = subCm.getIdentifier(o, POJO);
			if (id != null) {
				Serializable idName = subCm.getIdentifierPropertyName();
				crit.add(Restrictions.eq(field + "." + idName, id));
			} else {
				crit.createCriteria(field).add(Example.create(o));
			}
		}
		return crit;
	}
	@Transactional(isolation=Isolation.DEFAULT,readOnly=true)
	 protected Pagination findByCriteria(Criteria crit, int pageNo,
			int pageSize, Projection projection, Order... orders) {
		int totalCount = ((Number) crit.setProjection(Projections.rowCount())
				.uniqueResult()).intValue();
		Pagination p = new Pagination(pageNo, pageSize, totalCount);
		if (totalCount < 1) {
			p.setList(new ArrayList());
			return p;
		}
		crit.setProjection(projection);
		if (projection == null) {
			crit.setResultTransformer(Criteria.ROOT_ENTITY);
		}
		if (orders != null) {
			for (Order order : orders) {
				crit.addOrder(order);
			}
		}
		crit.setFirstResult(p.getFirstResult());
		crit.setMaxResults(p.getPageSize());
		p.setList(crit.list());
		return p;
	}

	static final class NotBlankPropertySelector implements PropertySelector {
		private static final long serialVersionUID = 1L;

		public boolean include(Object object, String property, Type type) {
			return object != null
					&& !(object instanceof String && StringUtils
							.isBlank((String) object));
		}
	}
	public Pagination findAll(int pageNo, int pageSize, OrderBy... orders) {
		Criteria crit = createCriteria();
		return findByCriteria(crit, pageNo, pageSize, null, OrderBy
				.asOrders(orders));
	}
	protected Criteria createCriteria(Criterion... criterions) {
		Criteria criteria = getSession().createCriteria(getPersistentClass());
		for (Criterion c : criterions) {
			criteria.add(c);
		}
		return criteria;
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	public void setPersistentClass(Class<T> persistentClass) {
		this.persistentClass = persistentClass;
	}

	public Class<T> getPersistentClass() {
		return persistentClass;
	}
	
}


package com.xangqun.page;

/**
 * 可分页接口
 * @author xangqun
 *
 */
public interface Paginable {

	public int getTotalCount();//总数
	
	public int getTotalPage(); //总分页
	
	public boolean isFirst(); //是否第一页
	
	public boolean isLast();  //是否最后页
	
	public int getPageSize(); //每页显示个数
	
	public int getcurrentPage();  //取得当前页
	
	public int getNextPage();  //取得下一页
	
	public int getPrePage();  //取得前一页
}

package com.xangqun.page;

public class SimplePage implements Paginable {

	public static final int DEFAULT_COUNT = 10;
	
	protected int currentPage; //当前页号
	protected int pageSize; //每页记录数
	protected int totalCount; //总记录数
	protected int totalPage;
	
	public SimplePage(){};

	public SimplePage(int currentPage, int pageSize, int totalCount) {
		this.currentPage = currentPage<0?1:currentPage;
		this.pageSize = pageSize<0?10:pageSize;
		this.totalCount = totalCount<0?0:totalCount;
		if ((this.currentPage - 1) * this.pageSize >= totalCount) {
			this.currentPage = totalCount / pageSize;
		}
	}

	/**
	 * 调整分页参数,使合理化
	 */
	public void adjustPage() {
		if (totalCount <= 0) {
			totalCount = 0;
		}
		if (pageSize <= 0) {
			pageSize = DEFAULT_COUNT;
		}
		if (currentPage <= 0) {
			currentPage = 1;
		}
		if ((currentPage - 1) * pageSize >= totalCount) {
			currentPage = totalCount / pageSize;
		}
	}
	
	@Override
	public int getcurrentPage() {
		return currentPage;
	}

	@Override
	public int getPageSize() {
		return pageSize;
	}
	
	@Override
	public int getNextPage() {
		return isLast()?currentPage:(currentPage+1);
	}
	
	@Override
	public int getPrePage() {
		return isFirst()?currentPage:(currentPage-1);
	}

	@Override
	public int getTotalCount() {
		return totalCount;
	}

	@Override
	public int getTotalPage() {
		return (totalCount%pageSize!=0||totalCount==0)?(totalCount/pageSize+1):totalCount/pageSize;
	}

	@Override
	public boolean isFirst() {
		return (currentPage<=1)?true:false;
	}

	@Override
	public boolean isLast() {
		return currentPage>=totalCount?true:false;
	}

	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public void setTotalCount(int totalCount) {
		this.totalCount = totalCount;
	}

	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}	
}

package com.xangqun.page;

import java.io.Serializable;
import java.util.List;
/**
 * 分页实现
 * @author xangqun
 *
 */
public class Pagination extends SimplePage implements Paginable,Serializable {

	private static final long serialVersionUID = 1L;
	public List<? extends Object> list;
	
	public Pagination() {
	}

	public Pagination(int currentPage, int pageSize, int totalCount) {
		super(currentPage, pageSize, totalCount);
	}

	public Pagination(int currentPage, int pageSize, int totalCount, List<? extends Object> list) {
		super(currentPage, pageSize, totalCount);
		this.list = list;
	}

	public int getFirstResult() {
		return (currentPage - 1) * pageSize;
	}

	public List<? extends Object> getList() {
		return list;
	}

	public void setList(List<? extends Object> list) {
		this.list = list;
	}
	
}

package com.xangqun.page;

import java.io.Serializable;

public class Condition implements Serializable {
	private static final long serialVersionUID = 1L;
	protected String field;

	public String getField() {
		return field;
	}
}

package com.xangqun.page;

public class Nullable  extends Condition {

	private static final long serialVersionUID = 1L;
	private boolean isNull;

	public Nullable(String field, boolean isNull) {
		this.field = field;
		this.isNull = isNull;
	}

	public static Nullable isNull(String field) {
		return new Nullable(field, true);
	}

	public static Nullable isNotNull(String field) {
		return new Nullable(field, false);
	}

	public boolean isNull() {
		return isNull;
	}
}

package com.xangqun.page;

import org.hibernate.criterion.Order;

public class OrderBy extends Condition{

	private static final long serialVersionUID = 1L;
	public static enum OrderType {
		ASC, DESC
	}
	private OrderType orderType;
	
	public OrderBy(){}
	public OrderBy(String field,OrderType orderType){
		this.field=field;
		this.orderType=orderType;
	}
	
	public static OrderBy asc(String field) {
		return new OrderBy(field, OrderType.ASC);
	}

	public static OrderBy desc(String field) {
		return new OrderBy(field, OrderType.DESC);
	}
	
	public Order getOrder(){
		Order order = null;
		if (OrderType.ASC == orderType) {
			order = Order.asc(getField());
		} else if (OrderType.DESC == orderType) {
			order = Order.desc(getField());
		}
		return order;
	}
	
	public static Order[] asOrders(OrderBy[] orderBys) {
		if (orderBys != null) {
			Order[] orders = new Order[orderBys.length];
			for (int i = 0; i < orderBys.length; i++) {
				orders[i] = orderBys[i].getOrder();
			}
			return orders;
		} else {
			return null;
		}

	}
}