通过子类实现父类泛型接口
父类接口
package com.test; import java.awt.datatransfer.StringSelection; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; /** * Created by huanl on 2017/7/19. */ public class Atest<T> { private Class<T> entityClass; public Atest(){ System.out.println("A construct"); Object obj = getClass(); System.out.println(obj.toString()); //获取当前操作类的父类 Type genType = getClass().getGenericSuperclass(); System.out.println(genType.toString()); //当前类实现类泛型接口 if(genType instanceof ParameterizedType){ //参数化类型 ParameterizedType parameterizedType = (ParameterizedType)genType; //返回此类型实际类型的数组 Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); entityClass = (Class)actualTypeArguments[0]; }else{ entityClass = (Class<T>) genType; } } }
子类
package com.test; /** * Created by huanl on 2017/7/19. */ public class BTest extends Atest<BTest>{ public BTest() { System.out.printf("B construct"); } }
通过泛型将子类传递到父类中,并调用子类的一些固定的方法,适用于Srping Hibernate BaseDao
package com.smart.dao; import org.hibernate.Query; import org.hibernate.Session; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate4.HibernateTemplate; import org.springframework.util.Assert; import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.sql.Statement; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * DAO基类,其它DAO可以直接继承这个DAO,不但可以复用共用的方法,还可以获得泛型的好处。 */ public class BaseDao<T>{ private Class<T> entityClass; private HibernateTemplate hibernateTemplate; /** * 通过反射获取子类确定的泛型类 */ public BaseDao() { Type genType = getClass().getGenericSuperclass(); Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); entityClass = (Class) params[0]; } /** * 根据ID加载PO实例 * * @param id * @return 返回相应的持久化PO实例 */ public T load(Serializable id) { return (T) getHibernateTemplate().load(entityClass, id); } /** * 根据ID获取PO实例 * * @param id * @return 返回相应的持久化PO实例 */ public T get(Serializable id) { return (T) getHibernateTemplate().get(entityClass, id); } /** * 获取PO的所有对象 * * @return */ public List<T> loadAll() { return getHibernateTemplate().loadAll(entityClass); } /** * 保存PO * * @param entity */ public void save(T entity) { getHibernateTemplate().save(entity); } /** * 删除PO * * @param entity */ public void remove(T entity) { getHibernateTemplate().delete(entity); } /** * 删除tableNames数据 * */ public void removeAll(String tableName) { getSession().createSQLQuery("truncate TABLE " + tableName +"").executeUpdate(); } /** * 更改PO * * @param entity */ public void update(T entity) { getHibernateTemplate().update(entity); } /** * 执行HQL查询 * * @param hql * @return 查询结果 */ public List find(String hql) { return this.getHibernateTemplate().find(hql); } /** * 执行带参的HQL查询 * * @param hql * @param params * @return 查询结果 */ public List find(String hql, Object... params) { return this.getHibernateTemplate().find(hql,params); } /** * 对延迟加载的实体PO执行初始化 * @param entity */ public void initialize(Object entity) { this.getHibernateTemplate().initialize(entity); } /** * 分页查询函数,使用hql. * * @param pageNo 页号,从1开始. */ public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values) { Assert.hasText(hql); Assert.isTrue(pageNo >= 1, "pageNo should start from 1"); // Count查询 String countQueryString = " select count (*) " + removeSelect(removeOrders(hql)); List countlist = getHibernateTemplate().find(countQueryString, values); long totalCount = (Long) countlist.get(0); if (totalCount < 1) return new Page(); // 实际查询返回分页对象 int startIndex = Page.getStartOfPage(pageNo, pageSize); Query query = createQuery(hql, values); List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list(); return new Page(startIndex, totalCount, pageSize, list); } /** * 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置. * 留意可以连续设置,如下: * <pre> * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list(); * </pre> * 调用方式如下: * <pre> * dao.createQuery(hql) * dao.createQuery(hql,arg0); * dao.createQuery(hql,arg0,arg1); * dao.createQuery(hql,new Object[arg0,arg1,arg2]) * </pre> * * @param values 可变参数. */ public Query createQuery(String hql, Object... values) { Assert.hasText(hql); Query query = getSession().createQuery(hql); for (int i = 0; i < values.length; i++) { query.setParameter(i, values[i]); } return query; } /** * 去除hql的select 子句,未考虑union的情况,用于pagedQuery. * * @see #pagedQuery(String,int,int,Object[]) */ private static String removeSelect(String hql) { Assert.hasText(hql); int beginPos = hql.toLowerCase().indexOf("from"); Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'"); return hql.substring(beginPos); } /** * 去除hql的orderby 子句,用于pagedQuery. * * @see #pagedQuery(String,int,int,Object[]) */ private static String removeOrders(String hql) { Assert.hasText(hql); Pattern p = Pattern.compile("order\s*by[\w|\W|\s|\S]*", Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(hql); StringBuffer sb = new StringBuffer(); while (m.find()) { m.appendReplacement(sb, ""); } m.appendTail(sb); return sb.toString(); } public HibernateTemplate getHibernateTemplate() { return hibernateTemplate; } @Autowired public void setHibernateTemplate(HibernateTemplate hibernateTemplate) { this.hibernateTemplate = hibernateTemplate; } public Session getSession() { return hibernateTemplate.getSessionFactory().getCurrentSession(); } }
子类实现BaseDao就会实现Hibernate的一些通用方法
子类只需要实现一些特定的方法就行
package com.smart.dao; import com.smart.domain.Post; import org.springframework.stereotype.Repository; /** * Post的DAO类 * */ @Repository public class PostDao extends BaseDao<Post> { private static final String GET_PAGED_POSTS = "from Post where topic.topicId =? order by createTime desc"; private static final String DELETE_TOPIC_POSTS = "delete from Post where topic.topicId=?"; public Page getPagedPosts(int topicId, int pageNo, int pageSize) { return pagedQuery(GET_PAGED_POSTS,pageNo,pageSize,topicId); } /** * 删除主题下的所有帖子 * @param topicId 主题ID */ public void deleteTopicPosts(int topicId) { getHibernateTemplate().bulkUpdate(DELETE_TOPIC_POSTS,topicId); } }