电商项目笔记之二:自定义带泛型的DaoSupport<T>类

本文介绍了一种自定义泛型DAO的设计方案,通过在项目中实现一个泛型的Dao支持类来替代Spring的HibernateDaoSupport,使得DAO层更加灵活且易于维护。此设计不仅实现了泛型的支持,还提供了统一的查询接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


这个项目里所有的DaoImpl没有直接继承Spring的HibernateDaoSupport,使用其中常用的方法

而是自己实现了一个带泛型的Dao支持类 ,多封装了一层以后, 具体的Dao再去继承这个支持类, 非常的nb啊.


想了一下这样设计的好处, 一是等于在底层实现了泛型 ,二是自己设计查询语句的传参(适配器) . 多一层封装还是有必要的.


不过我觉得继承方式有待改进, 项目中用的是接口+继承的菱形继承.

我想的解决方案是: 不如在定义好DaoSupport<T>类之后 ,具体的XxxDaoImpl直接继承于DaoSupport<T>再实现业务的IXxxDao接口 ,而IXxxDao接口只去定义自己需要的操作就足够了 就别再继承于最根上的Dao了(别用的着,用不着的方法都继承过来).




一:支持类

这个是菱形的顶端

public interface BaseDao<T> {
	//基本数据库操作方法
	public void save(Object obj);//保存数据
	//saveOrUpdate...update...

	public T get(Serializable entityId);//加载实体对象
	public T load(Serializable entityId);//加载实体对象
	public Object uniqueResult(String hql, Object[] queryParams);//使用hql语句操作
	//分页操作
	public long getCount();//获取总信息数
	public PageModel<T> find(int pageNo, int maxResult);//普通分页操作
	public PageModel<T> find(int pageNo, int maxResult,String where, Object[] queryParams);//搜索信息分页方法
	public PageModel<T> find(int pageNo, int maxResult,Map<String, String> orderby);//按指定条件排序分页方法
	public PageModel<T> find(String where, Object[] queryParams,
			Map<String, String> orderby, int pageNo, int maxResult);//按指定条件分页和排序的分页方法
}


二:DaoSupport<T>

是默认的具体实现

1.@Transactional是Spring事务处理边界的声明, 感觉还是在xml里写明白了好一点...

2.实现了spring提供的HibernateTemplate

@Transactional
@SuppressWarnings("unchecked")
public class DaoSupport<T> implements BaseDao<T>{
	// 泛型的类型
	protected Class<T> entityClass = GenericsUtils.getGenericType(this.getClass());
	// Hibernate模板
	@Autowired
	protected HibernateTemplate template;
	
	public HibernateTemplate getTemplate() {
		return template;
	}


3.泛型转换工具

entityClass 属性提供了泛型的具体类型

用反射写的, 能看懂 写不出来...记录一下

	public static Class getGenericType(Class clazz){
		Type genType = clazz.getGenericSuperclass();//得到泛型父类  
		Type[] types = ((ParameterizedType) genType).getActualTypeArguments();
		if (!(types[0] instanceof Class)) {
            return Object.class;   
        } 
		return (Class) types[0];
	}


	public static String getGenericName(Class clazz){
		return clazz.getSimpleName();
	}


4.封装HQL

这个封装的是uniqueResult,

封装之后 第一个参数是hql语句, 第二个参数是查询条件

回调结果

	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public Object uniqueResult(final String hql,final Object[] queryParams) {
		return getTemplate().execute(new HibernateCallback() {
			
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				Query query = session.createQuery(hql);//执行查询
				setQueryParams(query, queryParams);//设置查询参数
				return query.uniqueResult();
			}
		});
	}


这个find封装的就比较nb了 ,

参数一是查询条件,

参数二是参数,

三是排序的依据 ,

四五是分页的参数

这样具体业务中, 所有查询都能用一个find()搞定, 不同的用途只是传参不一样而已

@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public PageModel<T> find(final String where, final Object[] queryParams,
			final Map<String, String> orderby, final int pageNo,
			final int maxResult) {
		final PageModel<T> pageModel = new PageModel<T>();//实例化分页对象
		pageModel.setPageNo(pageNo);//设置当前页数
		pageModel.setPageSize(maxResult);//设置每页显示记录数
		getTemplate().execute(new HibernateCallback() {//执行内部方法
			
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				String hql = new StringBuffer().append("from ")//添加form字段
								.append(GenericsUtils.getGenericName(entityClass))//添加对象类型
								.append(" ")//添加空格
								.append(where == null ? "" : where)//如果where为null就添加空格,反之添加where
								.append(createOrderBy(orderby))//添加排序条件参数
								.toString();//转化为字符串
				Query query = session.createQuery(hql);//执行查询
				setQueryParams(query,queryParams);//为参数赋值
				List<T> list = null;//定义List对象
				// 如果maxResult<0,则查询所有
				if(maxResult < 0 && pageNo < 0){
					list = query.list();//将查询结果转化为List对象
				}else{
					list = query.setFirstResult(getFirstResult(pageNo, maxResult))//设置分页起始位置
								.setMaxResults(maxResult)//设置每页显示的记录数
								.list();//将查询结果转化为List对象
					//定义查询总记录数的hql语句
					hql = new StringBuffer().append("select count(*) from ")//添加hql语句
									.append(GenericsUtils.getGenericName(entityClass))//添加对象类型
									.append(" ")//添加空格
									.append(where == null ? "" : where)//如果where为null就添加空格,反之添加where
									.toString();//转化为字符串
					query = session.createQuery(hql);//执行查询
					setQueryParams(query,queryParams);//设置hql参数
					int totalRecords = ((Long) query.uniqueResult()).intValue();//类型转换
					pageModel.setTotalRecords(totalRecords);//设置总记录数
				}
				pageModel.setList(list);//将查询的list对象放入实体对象中
				return null;
			}
		});
		return pageModel;//返回分页的实体对象
	}





三:业务Dao接口

就是IXxxDao

这继承了另一个顶级的接口,为的是填充更多的抽象方法

public interface UserDao extends BaseDao<User> {
	public User login(String username, String password);
	public boolean isUnique(String username);
}


四:业务Dao的实现

就是XxxDaoImpl

它继承于DaoSupport<>是为了继承基本的get ,load ,find方法

实现匹配的业务Dao是要实现具体的 新的方法

public class UserDaoImpl extends DaoSupport<User> implements UserDao {

	//@Override
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public User login(String username, String password) {
		if(username != null && password != null){//如果用户名和密码不为空
			String where = "where username=? and password=?";//设置查询条件
			Object[] queryParams = {username,password};//设置参数对象数组
			List<User> list = find(-1, -1, where, queryParams).getList();//执行查询方法
			if(list != null && list.size() > 0){//如果list集合不为空
				return list.get(0);//返回List中的第一个存储对象
			}
		}
		return null;//返回空值
	}











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值