一、定义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];
}
}