很nice的泛型dao父类

本文介绍了一个通用的DAO接口及其实现,提供了基本的数据访问操作如查询、更新和删除等,并实现了泛型来增强类型安全性。

1.接口



package net.shopxx.dao;

import java.io.Serializable;
import java.util.List;

import net.shopxx.bean.Pager;

import org.hibernate.criterion.DetachedCriteria;

/**
 * Dao接口 - Dao基接口
 * ============================================================================
 * 版权所有 2008-2010 长沙鼎诚软件有限公司,并保留所有权利。
 * ----------------------------------------------------------------------------
 * 提示:在未取得SHOP++商业授权之前,您不能将本软件应用于商业用途,否则SHOP++将保留追究的权力。
 * ----------------------------------------------------------------------------
 * 官方网站:http://www.shopxx.net
 * ----------------------------------------------------------------------------
 * KEY: SHOPXX0FF87D88DFDA50E4762E39A4625B158C
 * ============================================================================
 */

public interface BaseDao<T, PK extends Serializable> {

 /**
 * 根据ID获取实体对象.
 * 
 * @param id
 * 记录ID
 * @return 实体对象
 */
 public T get(PK id);

 /**
 * 根据ID获取实体对象.
 * 
 * @param id
 * 记录ID
 * @return 实体对象
 */
 public T load(PK id);

 /**
 * 根据ID数组获取实体对象集合.
 * 
 * @param ids
 * ID对象数组
 * 
 * @return 实体对象集合
 */
 public List<T> get(PK[] ids);

 /**
 * 根据属性名和属性值获取实体对象.
 * 
 * @param propertyName
 * 属性名称
 * @param value
 * 属性值
 * @return 实体对象
 */
 public T get(String propertyName, Object value);

 /**
 * 根据属性名和属性值获取实体对象集合.
 * 
 * @param propertyName
 * 属性名称
 * @param value
 * 属性值
 * @return 实体对象集合
 */
 public List<T> getList(String propertyName, Object value);

 /**
 * 获取所有实体对象集合.
 * 
 * @return 实体对象集合
 */
 public List<T> getAll();

 /**
 * 获取所有实体对象总数.
 * 
 * @return 实体对象总数
 */
 public Long getTotalCount();

 /**
 * 根据属性名、修改前后属性值判断在数据库中是否唯一(若新修改的值与原来值相等则直接返回true).
 * 
 * @param propertyName
 * 属性名称
 * @param oldValue
 * 修改前的属性值
 * @param oldValue
 * 修改后的属性值
 * @return boolean
 */
 public boolean isUnique(String propertyName, Object oldValue, Object newValue);

 /**
 * 根据属性名判断数据是否已存在.
 * 
 * @param propertyName
 * 属性名称
 * @param value
 * 值
 * @return boolean
 */
 public boolean isExist(String propertyName, Object value);

 /**
 * 保存实体对象.
 * 
 * @param entity
 * 对象
 * @return ID
 */
 public PK save(T entity);

 /**
 * 更新实体对象.
 * 
 * @param entity
 * 对象
 */
 public void update(T entity);

 /**
 * 删除实体对象.
 * 
 * @param entity
 * 对象
 * @return
 */
 public void delete(T entity);

 /**
 * 根据ID删除实体对象.
 * 
 * @param id
 * 记录ID
 */
 public void delete(PK id);

 /**
 * 根据ID数组删除实体对象.
 * 
 * @param ids
 * ID数组
 */
 public void delete(PK[] ids);

 /**
 * 刷新session.
 * 
 */
 public void flush();

 /**
 * 清除Session.
 * 
 */
 public void clear();

 /**
 * 清除某一对象.
 * 
 * @param object
 * 需要清除的对象
 */
 public void evict(Object object);

 /**
 * 根据Pager对象进行查询(提供分页、查找、排序功能).
 * 
 * @param pager
 * Pager对象
 * @return Pager对象
 */
 public Pager findByPager(Pager pager);

 /**
 * 根据Pager和DetachedCriteria对象进行查询(提供分页、查找、排序功能).
 * 
 * @param pager
 * Pager对象
 * @return Pager对象
 */
 public Pager findByPager(Pager pager, DetachedCriteria detachedCriteria);

}

 

 2,实现:

package net.shopxx.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.annotation.Resource;

import net.shopxx.bean.Pager;
import net.shopxx.bean.Pager.OrderType;
import net.shopxx.dao.BaseDao;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

/**
 * Dao实现类 - Dao实现类基类
 * ============================================================================
 * 版权所有 2008-2010 长沙鼎诚软件有限公司,并保留所有权利。
 * ----------------------------------------------------------------------------
 * 提示:在未取得SHOP++商业授权之前,您不能将本软件应用于商业用途,否则SHOP++将保留追究的权力。
 * ----------------------------------------------------------------------------
 * 官方网站:http://www.shopxx.net
 * ----------------------------------------------------------------------------
 * KEY: SHOPXXCED32589174C8D5905B5D0A02A2F33DF
 * ============================================================================
 */

@Repository
public class BaseDaoImpl<T, PK extends Serializable> implements BaseDao<T, PK> {

	private Class<T> entityClass;
	protected SessionFactory sessionFactory;

	@SuppressWarnings("unchecked")
	public BaseDaoImpl() {
		this.entityClass = null;
        Class c = getClass();
        Type type = c.getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            Type[] parameterizedType = ((ParameterizedType) type).getActualTypeArguments();
            this.entityClass = (Class<T>) parameterizedType[0];
        }
	}

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

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

	@SuppressWarnings("unchecked")
	public T get(PK id) {
		Assert.notNull(id, "id is required");
		return (T) getSession().get(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	public T load(PK id) {
		Assert.notNull(id, "id is required");
		return (T) getSession().load(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	public List<T> get(PK[] ids) {
		Assert.notEmpty(ids, "ids must not be empty");
		String hql = "from " + entityClass.getName() + " as model where model.id in(:ids)";
		return getSession().createQuery(hql).setParameterList("ids", ids).list();
	}

	@SuppressWarnings("unchecked")
	public T get(String propertyName, Object value) {
		Assert.hasText(propertyName, "propertyName must not be empty");
		Assert.notNull(value, "value is required");
		String hql = "from " + entityClass.getName() + " as model where model." + propertyName + " = ?";
		return (T) getSession().createQuery(hql).setParameter(0, value).uniqueResult();
	}
	
	@SuppressWarnings("unchecked")
	public List<T> getList(String propertyName, Object value) {
		Assert.hasText(propertyName, "propertyName must not be empty");
		Assert.notNull(value, "value is required");
		String hql = "from " + entityClass.getName() + " as model where model." + propertyName + " = ?";
		return getSession().createQuery(hql).setParameter(0, value).list();
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll() {
		String hql = "from " + entityClass.getName();
		return getSession().createQuery(hql).list();
	}
	
	public Long getTotalCount() {
		String hql = "select count(*) from " + entityClass.getName();
		return (Long) getSession().createQuery(hql).uniqueResult();
	}

	public boolean isUnique(String propertyName, Object oldValue, Object newValue) {
		Assert.hasText(propertyName, "propertyName must not be empty");
		Assert.notNull(newValue, "newValue is required");
		if (newValue == oldValue || newValue.equals(oldValue)) {
			return true;
		}
		if (newValue instanceof String) {
			if (oldValue != null && StringUtils.equalsIgnoreCase((String) oldValue, (String) newValue)) {
				return true;
			}
		}
		T object = get(propertyName, newValue);
		return (object == null);
	}
	
	public boolean isExist(String propertyName, Object value) {
		Assert.hasText(propertyName, "propertyName must not be empty");
		Assert.notNull(value, "value is required");
		T object = get(propertyName, value);
		return (object != null);
	}

	@SuppressWarnings("unchecked")
	public PK save(T entity) {
		Assert.notNull(entity, "entity is required");
		return (PK) getSession().save(entity);
	}

	public void update(T entity) {
		Assert.notNull(entity, "entity is required");
		getSession().update(entity);
	}

	public void delete(T entity) {
		Assert.notNull(entity, "entity is required");
		getSession().delete(entity);
	}

	public void delete(PK id) {
		Assert.notNull(id, "id is required");
		T entity = load(id);
		getSession().delete(entity);
	}

	public void delete(PK[] ids) {
		Assert.notEmpty(ids, "ids must not be empty");
		for (PK id : ids) {
			T entity = load(id);
			getSession().delete(entity);
		}
	}

	public void flush() {
		getSession().flush();
	}

	public void clear() {
		getSession().clear();
	}

	public void evict(Object object) {
		Assert.notNull(object, "object is required");
		getSession().evict(object);
	}
	
	public Pager findByPager(Pager pager) {
		if (pager == null) {
			pager = new Pager();
		}
		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(entityClass);
		return findByPager(pager, detachedCriteria);
	}

	public Pager findByPager(Pager pager, DetachedCriteria detachedCriteria) {
		if (pager == null) {
			pager = new Pager();
		}
		Integer pageNumber = pager.getPageNumber();
		Integer pageSize = pager.getPageSize();
		String property = pager.getProperty();
		String keyword = pager.getKeyword();
		String orderBy = pager.getOrderBy();
		OrderType orderType = pager.getOrderType();
		
		Criteria criteria = detachedCriteria.getExecutableCriteria(getSession());
		if (StringUtils.isNotEmpty(property) && StringUtils.isNotEmpty(keyword)) {
			String propertyString = "";
			if (property.contains(".")) {
				String propertyPrefix = StringUtils.substringBefore(property, ".");
				String propertySuffix = StringUtils.substringAfter(property, ".");
				criteria.createAlias(propertyPrefix, "model");
				propertyString = "model." + propertySuffix;
			} else {
				propertyString = property;
			}
			criteria.add(Restrictions.like(propertyString, "%" + keyword + "%"));
		}
		
		Integer totalCount = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();
		
		criteria.setProjection(null);
		criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		criteria.setFirstResult((pageNumber - 1) * pageSize);
		criteria.setMaxResults(pageSize);
		if (StringUtils.isNotEmpty(orderBy) && orderType != null) {
			if (orderType == OrderType.asc) {
				criteria.addOrder(Order.asc(orderBy));
			} else {
				criteria.addOrder(Order.desc(orderBy));
			}
		}
		pager.setTotalCount(totalCount);
		pager.setList(criteria.list());
		return pager;
	}

}

 

3.继承

public class AdminDaoImpl extends BaseDaoImpl<Admin, int>{}
 
<think>好的,我现在需要解释Java中关于子类继承父类的概念。用户可能对的基础有一定了解,但需要更深入的理解子类如何继承父类。首先,我得回忆一下Java的基本机制,特别是继承时的类参数处理。 首先,父类如果是类,子类在继承时可以选择保留父类参数,或者具体化父类的类参数。例如,父类可能是class Parent<T>,子类可以是class Child<T> extends Parent<T>,这样Child也成了类,保留了父类。或者,子类可能指定具体的类,如class Child extends Parent<String>,此时父类的T被确定为String,子类不需要再声明参数。 接下来需要考虑类擦除的问题。Java的在编译后会被擦除,所以运行时无法获取类参数的具体信息。这可能会影响子类继承时的行为,比如方法重写和类检查。 然后,用户可能需要了解子类如何添加自己的参数。例如,子类可以同时拥有自己的和继承父类的,如class Child<S, T> extends Parent<T>,这样父类使用T,而子类引入新的S。这种情况下,实例化子类时需要指定两个类参数。 另外,方法的继承也需要考虑。子类可以重写父类方法,但必须保持类参数的兼容性。如果父类的方法使用了,子类在重写时可以使用相同或更具体的类,但需要注意类擦除可能导致的问题,比如方法签名冲突。 还需要讨论通配符和边界的问题。父类可能使用了extends或super通配符,子类在继承时如何处理这些情况。例如,如果父类有<? extends Number>,子类可能需要适配这个边界,或者进一步限制类参数。 可能的误区包括误以为子类继承父类时会自动实例化类参数,或者混淆了类继承和方法的重写。需要指出子类必须显式处理父类的类参数,否则可能导致编译错误。 最后,应该通过示例代码来具体说明不同情况下的用法,比如保留父类、具体化类参数、子类添加新参数等。这些例子可以帮助用户更直观地理解概念。 总结一下,我需要分步骤解释子类继承父类的不同情况,强调类参数的处理方式,类擦除的影响,以及可能的错误用法。同时,提供清晰的代码示例来辅助说明,确保用户能够逐步理解这一机制。</think>在Java中,子类继承父类时,参数的处理需要特别注意。以下是分步说明: --- ### 1. **基础继承:保留父类** 子类可以继续使用父类参数,此时子类自身也需声明为类。 ```java class Parent<T> { T data; void setData(T data) { this.data = data; } } // 子类保留父类参数 class Child<T> extends Parent<T> { void print() { System.out.println(data); } } ``` - **使用示例**: ```java Child<String> child = new Child<>(); child.setData("Hello"); // 类安全 ``` --- ### 2. **具体化父类** 子类可以直接为父类指定具体类参数,此时子类不再是类。 ```java class Child extends Parent<String> { void print() { System.out.println(data.toUpperCase()); } } ``` - **使用示例**: ```java Child child = new Child(); child.setData("world"); // 父类T已被固定为String ``` --- ### 3. **子类添加新参数** 子类可以同时保留父类并引入自己的参数。 ```java class Child<S, T> extends Parent<T> { S metadata; void setMetadata(S metadata) { this.metadata = metadata; } } ``` - **使用示例**: ```java Child<Integer, String> child = new Child<>(); child.setData("Java"); child.setMetadata(100); // S=Integer, T=String ``` --- ### 4. **边界与继承** 若父类定义了边界,子类必须遵守或更严格。 ```java class Parent<T extends Number> { /* ... */ } // 合法:子类沿用父类边界 class Child1<T extends Number> extends Parent<T> {} // 合法:子类缩小边界 class Child2<T extends Integer> extends Parent<T> {} ``` --- ### 5. **类擦除的影响** 由于类擦除,以下代码会编译错误: ```java class Parent<T> { void setData(T data) { /* ... */ } } // 错误!重写方法因类擦除导致签名冲突 class Child extends Parent<String> { void setData(String data) { /* ... */ } // 实际编译后:setData(Object) // 与父类方法签名重复 } ``` **正确做法**:子类无需显式重写`setData`,直接继承即可。 --- ### 6. **方法的继承与重写** 子类可以重写父类方法,但需保持兼容性: ```java class Parent { <T> void process(T data) { /* ... */ } } class Child extends Parent { @Override <T> void process(T data) { /* ... */ } // 合法重写 } ``` --- ### 关键点总结 1. **保留**:子类声明相同的参数(如`Child<T>`),延续父类的灵活性。 2. **指定具体类**:子类直接固定父类(如`Child extends Parent<String>`)。 3. **边界**:子类的参数必须满足父类定义的类边界。 4. **类擦除陷阱**:避免因擦除导致方法签名冲突。 通过合理设计继承,可以实现类安全的代码复用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值