一、定义BaseDao接口
将对所有实体都进行的增删改查操作提取到一个接口里面,可以提高代码的可重用性
BaseDao<T> 接口:
package com.charlie.shop.dao.base; import java.util.List; public interface BaseDao<T> { /** * 添加 一个对象 * * @param t 实体对象 */ public void save(T t); /** * 删除一个对象 * * @param id 实体id号 */ public void delete(Long...ids); /** * 更新一个对象 * * @param t 实体对象 */ public void update(T t); /** * 根据id号查询一个对象 * * @param id 实体id号 * @return 返回一个实体对象,查找失败则返回null */ public T getById(Long id); /** * 根据id数组查询对象 * * @param ids id数组 * @return 实体列表 */ public List<T> getByIds(Long[] ids); /** * 查询所有 * * @return */ public List<T> findAll(); }
二、定义抽象BaseDaoImpl类去实现BaseDao接口
要实现该接口中的方法时,有一个关键的问题需要解决,那就是必须获得参数类型T的真正类型信息,即T对应的Class对象。
比如,在实现getById(Long id)方法时,必然需要用到Hibernate API中的
Session.get(Class clazz,Serializable id)方法,这个方法的第一个参数就是需要一个Class对象;
另外,在拼接HQL语句时,也需要用到实体类的类名,这也需要通过其Class对象来获得。
那么,该如何获得T的Class对象呢?
重点关注JDK API中的以下方法:
getClass
public final Class<?> getClass()
-
返回此
Object
的运行时类。返回的Class
对象是由所表示类的static synchronized
方法锁定的对象。实际结果类型是
Class<? extends |X|>
,其中|X|
表示清除表达式中的静态类型,该表达式调用getClass
。 例如,以下代码片段中不需要强制转换:Number n = 0;
Class<? extends Number> c = n.getClass();
-
-
返回:
-
表示此对象运行时类的
Class
对象。
-
表示此对象运行时类的
getGenericSuperclass
public Type getGenericSuperclass()
-
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type。
如果超类是参数化类型,则返回的 Type 对象必须准确反映源代码中所使用的实际类型参数。如果以前未曾创建表示超类的参数化类型,则创建这个类型。有关参数化类型创建过程的语义,请参阅
ParameterizedType
声明。如果此 Class 表示 Object 类、接口、基本类型或 void,则返回 null。如果此对象表示一个数组类,则返回表示 Object 类的 Class 对象。 -
-
-
返回:
- 此对象所表示的类的超类 抛出:
-
GenericSignatureFormatError
- 如果常规类签名不符合 Java Virtual Machine Specification, 3rd edition 规定的格式 -
TypeNotPresentException
- 如果常规超类引用不存在的类型声明 -
MalformedParameterizedTypeException
- 如果常规超类引用的参数化类型由于某种原因无法实例化
getActualTypeArguments
Type[] getActualTypeArguments()
-
返回表示此类型实际类型参数的 Type 对象的数组。
注意,在某些情况下,返回的数组为空。如果此类型表示嵌套在参数化类型中的非参数化类型,则会发生这种情况。
-
-
-
返回:
- 表示此类型的实际类型参数的 Type 对象的数组 抛出:
-
TypeNotPresentException
- 如果任何实际类型参数引用不存在的类型声明 -
MalformedParameterizedTypeException
- 如果任何实际类型参数引用参数化类型,该类型出于某种原因无法被实例化
BaseDaoImpl.java
package com.charlie.shop.dao.base; import java.lang.reflect.ParameterizedType; import java.util.Collections; import java.util.List; import javax.annotation.Resource; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.transaction.annotation.Transactional; @SuppressWarnings("unchecked") @Transactional public abstract class BaseDaoImpl<T> implements BaseDao<T> { @Resource // 注入父类的属性,父类可以不用托管,只要子类有托管即可 private SessionFactory sessionFactory; // 泛型T的真实类型 protected Class<?> clazz = getGenericType(); @Override public void save(T t) { getSession().save(t); } @Override public void delete(Long... ids) { for (Long id : ids) { // 先取出对象 Object obj = getSession().get(clazz, id); if (obj != null) { getSession().delete(obj); } } } @Override public void update(T t) { if (t == null) { return; } else { getSession().update(t); } } @Override public T getById(Long id) { if (id == null) return null; return (T) getSession().get(clazz, id); } @Override public List<T> getByIds(Long[] ids) { if (ids == null || ids.length == 0) { return Collections.EMPTY_LIST; } return getSession().createQuery(// "FROM " + clazz.getSimpleName() + " WHERE id IN(:ids)")// .setParameterList("ids", ids)// .list(); } @Override public List<T> findAll() { return getSession().createQuery(// "FROM " + clazz.getSimpleName())// .list(); } /** * 返回一个会话 声明为protected修饰,可以让子类直接用 因为用到spring * 事务管理,所以要用getCurrentSession,不用openSession */ protected Session getSession() { return sessionFactory.getCurrentSession(); } /** * 获取泛型类型 */ protected Class<?> getGenericType() { ParameterizedType pt = (ParameterizedType) this.getClass() .getGenericSuperclass(); return (Class<?>) pt.getActualTypeArguments()[0]; } }