一般在建立工程的时候会根据不同的模块的功能来建包,
dao层的代码是用来访问数据库的,它通过操作domain领域层的对象,对数据库进行增删改查的操作。
但是,一般情况下,一个项目有多个表,对应到面向对象的语言就会相应的要创建多个类对象。进而根据对应的对象创建dao层的类,比如,有一个Person对象,如果要操作该对象的话,相应的就要创建PersonDaoImpl这个类来操作person这个对象,对它进行增删改查的操作,就要实现增删改查的代码。但是如果有十个,二十个对象,对应的要创建十个,二十个dao类,同时实现增删改查的代码,那么这样问题就来了,这些代码其实都是有相似的地方的,就是增删改查的代码都是一样的,只不过要操作的对象不一样吧了。
所以我们考虑到可以使用继承,接口的思想来实现代码的重用,抽出一个父类,ICommonDao是一个接口,CommonDaoImpl是该接口的实现。但是,是否要利用Object来指向所有的对象呢,其实这里我们使用的是泛型的技术来实现。
下面是给出的代码
public interface ICommonDao<T> {
/**
* <p>保存一条数据 </p>
*/
void save(T entity);
/**
*
* <p>保存多条数据 </p>
*/
void saveConllection(Collection<T> entities);
/**
* <p>删除一条数据 </p>
*/
void deleteById(Serializable id);
/**
* <p>根据id数组删除多条数据 </p>
*/
void deleteByIds(Collection<T> entities);
/**
* <p>更新一条数据 </p>
*/
void update(T entity);
/**
* <p>更新一条数据 </p>
*/
void partialRenewal(List<Object>keys,List<Object>params ,LinkedHashMap<String,Object> conditions);
/**
* <p>根据id查看一条数据 </p>
*/
T findEntityById(Serializable id);
/**
* <p>根据id数组查找多条数据 </p><br/>
* <P>由于数据库里面的实体是不能够重复的,所以这里使用Set集合</p>
*/
Set<T> findEntitiesByIds(Serializable ... ids);
/**
*
* <p>查找所有对象</p>
*/
Collection<T> findAll();
/**
*
*<p>根据多个条件查询数据</p>
*/
List<T> findCollectionByConditionNoPage(String condition,
Object[] params, LinkedHashMap<String, String> hashMap);
/**
*
*<p>根据多个条件查询数据,并且使用了二级缓存</p>
*/
List<T> findCollectionByConditionNoPageWithCache(String condition,
Object[] params, LinkedHashMap<String, String> hashMap);
}
上面定义一个公共的访问数据层的接口,已经抽取出公有的方法。
下面会定义一个类来实现这个接口。
public class CommonDaoImpl extends HibernateDaoSupport implements ICommonDao {
@SuppressWarnings("rawtypes")
private Class entityClass = GenericSuperClass.getActualTypeClass(this.getClass()) ;
//通过依赖注入SessionFactory类,获取hibernateTempalte对象
@Resource(name="sessionFactory")
public final void setSessionFactoryDI(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}
/**
* @Name: save
* @Description: 保存
* @Author: 张淼洁(作者)
* @Version: V1.00 (版本号)
* @Create Date: 2015-06-20 (创建日期)
* @Param T entity 保存对象
*/
public void save(T entity) {
this.getHibernateTemplate().save(entity);
}
/**
* @Name: deleteById
* @Description: 根据实体的id删除数据
* @Author: 张淼洁(作者)
* @Version: V1.00 (版本号)
* @Create Date: 2015-06-20 (创建日期)
* @Param Serializable id 实体的id字段
*/
public void deleteById(Serializable id) {
T entity = findEntityById(id);
this.getHibernateTemplate().delete(entity);
}
/**
* @Name: deleteByIds
* @Description: 根据实体的id删除数据
* @Author: 张淼洁(作者)
* @Version: V1.00 (版本号)
* @Create Date: 2015-06-20 (创建日期)
* @Param Serializable id 实体的id字段
*/
public void deleteByIds(Collection<T> entities) {
this.getHibernateTemplate().deleteAll(entities);
}
public void update(T entity) {
this.getHibernateTemplate().update(entity);
}
@SuppressWarnings("unchecked")
public T findEntityById(Serializable id) {
return (T) this.getHibernateTemplate().get(entityClass, id);
}
@SuppressWarnings("unchecked")
public Set<T> findEntitiesByIds(Serializable... ids) {
Set<T> set = new HashSet<T>();
for(int id=0; id<ids.length; id++){
set.add((T)this.getHibernateTemplate().get(entityClass, ids[id]));
}
return set;
}
@SuppressWarnings("unchecked")
public Collection<T> findAll() {
return this.getHibernateTemplate().find("from " + entityClass.getName());
}
/**根据条件进行模糊查询*/
@SuppressWarnings("rawtypes")
@Override
public List<T> findCollectionByConditionNoPage(String condition,
final Object[] params, LinkedHashMap<String, String> hashMap) {
/*
* web界面查询用户的信息,where默认为1=1,这样用户即使不选择任何条件,sql查询也不会出错。
*/
String hql = "from "+entityClass.getSimpleName() +" o where 1=1";
String orderby = "";
//判断是否需要排序
if(hashMap !=null){
orderby = orderByHql(hashMap);
}
//from SystemGroupUser o where 1=1 and o.name like ? and o.principal = ? order by o.id desc
final String finalHql = hql + condition + orderby;
System.out.println("hql : "+hql);
@SuppressWarnings({ "unchecked" })
List<T> list = (List<T>) this.getHibernateTemplate().execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException,
SQLException {
Query query = session.createQuery(finalHql);
for(int i=0;params!=null && i<params.length;i++){
query.setParameter(i, params[i]);
}
return query.list();
}
});
return list;
}
/**通过传递的排序集合语句(Map),获取对应的排序条件(String)*/
/**ORDER BY o.textDate ASC,o.textName DESC*/
private String orderByHql(LinkedHashMap<String, String> hashMap) {
StringBuffer order = new StringBuffer("");
if(hashMap != null && !hashMap.isEmpty()){
order.append(" order by ");
for(Map.Entry<String, String> map : hashMap.entrySet()){
order.append(map.getKey()+" "+map.getValue()+" ,");
}
order.deleteCharAt(order.length()-1);//去掉最后一个逗号
}
return order.toString();
}
/**
* @Name: partialRenewal
* @Description: 根据业务层传递的条件和要更新的字段进行局部的更新
* @Author: 张淼洁(作者)
* @Version: V1.00 (版本号)
* @Create Date: 2015-06-20 (创建日期)
* @Param params 要更新的字段
* condition 条件
*/
@Override
public void partialRenewal(List<Object>keys,List<Object>params ,LinkedHashMap<String,Object> conditions) {
//字段和实际的值数量要一致
if(keys.size()!=params.size()){
throw new RuntimeException("字段的数量和更新的值的数量不一致!");
}
//将集合对象转换为数组对象
Object[]keyArray = keys.toArray();
Object[]paramArray = params.toArray();
HibernateUtil hibernateUtil = HibernateUtil.getHibernateUtil();
Session session = HibernateUtil.getSession();
//定义查询的语句
/*String hql = "update "+getTableName4ClassName()+" set ";*/
String hql = "update "+ hibernateUtil.getTableName4ClassName(entityClass)+" set ";
//组织查询语句的关键字段
for(int i=0; i<keys.size(); i++){
if(i==0){
hql += ""+keyArray[i]+"= "+modifiedField(paramArray[i]) +"";
}else{
hql +=","+keyArray[i]+"= "+modifiedField(paramArray[i]) +"";
}
}
hql +=updateConditionByHql(conditions);
final String executeSQL = hql;
System.out.println("hql :"+hql);
session.beginTransaction();
SQLQuery query = session.createSQLQuery(executeSQL);
int result = query.executeUpdate();
System.out.println("一共有"+result+"条数据被影响!");
session.getTransaction().commit();
HibernateUtil.closeSession(session);
/*return result; */
}
/**
* @description:判断表字段的类型,从而是否进行字段的修饰
* @param type
* @return
*/
private String modifiedField(Object type){
if(type == null){
throw new RuntimeException("type 不能为空!");
}
StringBuffer sb = new StringBuffer();
if(type instanceof String){
String stringType = (String)type;
sb.append("'");
sb.append(stringType);
sb.append("'");
return new String(sb);
}else if(type instanceof Date){
String dateType =new SimpleDateFormat("yyyy-MM-dd").format(type);
sb.append("'");
System.out.println("date ==" +dateType);
sb.append(dateType);
sb.append("'");
return new String(sb);
}
return type+"";
}
/**
* @description 组织好更新的条件
* @param conditions
* @return
*/
private String updateConditionByHql(LinkedHashMap<String,Object> conditions){
if(conditions == null || conditions.keySet().size()<=0){
throw new RuntimeException("更新条件不能为空!");
}
StringBuffer sb = new StringBuffer();
sb.append(" where ");
for(Map.Entry<String, Object> entry:conditions.entrySet()){
sb.append(" "+entry.getKey()+"="+modifiedField(entry.getValue()));
}
System.out.println("更新条件为 "+new String(sb));
return new String(sb);
}
@SuppressWarnings("rawtypes")
@Override
public List<T> findCollectionByConditionNoPageWithCache(String condition,
final Object[] params, LinkedHashMap<String, String> hashMap) {
/*
* web界面查询用户的信息,where默认为1=1,这样用户即使不选择任何条件,sql查询也不会出错。
*/
String hql = "from "+entityClass.getSimpleName() +" o where 1=1";
String orderby = "";
//判断是否需要排序
if(hashMap !=null){
orderby = orderByHql(hashMap);
}
//from SystemGroupUser o where 1=1 and o.name like ? and o.principal = ? order by o.id desc
final String finalHql = hql + condition + orderby;
System.out.println("hql : "+hql);
@SuppressWarnings({ "unchecked" })
List<T> list = (List<T>) this.getHibernateTemplate().execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException,
SQLException {
Query query = session.createQuery(finalHql);
for(int i=0;params!=null && i<params.length;i++){
query.setParameter(i, params[i]);
}
//启用二级缓存存储数据
query.setCacheable(true);
return query.list();
}
});
return list;
}
@Override
public void saveConllection(Collection<T> entities) {
this.getHibernateTemplate().saveOrUpdateAll(entities);
}
}
上面的类中有一个行代码是很重要的
@SuppressWarnings("rawtypes")
private Class entityClass = GenericSuperClass.getActualTypeClass(this.getClass()) ;
通过一个工具类GenericSuperClass调用getActualTypeClass方法来获取真实的T泛型类型。
public class GenericSuperClass {
/**
*
* @param clazz
* @return class对象
* @description 将泛型转换为class类对象
*/
@SuppressWarnings("rawtypes")
public static Class getActualTypeClass(Class clazz){
ParameterizedType type = (ParameterizedType) clazz.getGenericSuperclass();
Class entityClass = (Class) type.getActualTypeArguments()[0];
return entityClass;
}
}
只要继承这个类并传入泛型类型,最后得到的entityClass对象就是传入的泛型的对象。
//通过依赖注入SessionFactory类,获取hibernateTempalte对象
@Resource(name=”sessionFactory”)
public final void setSessionFactoryDI(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}
因为CommonDaoImpl继承了HibernateDaoSupport这个类,所以可以使用这个类的对象方法this.getHibernateTemplate();获取得到hibernate的模板,这是Spring框架提供的。但是,一定要给这个类的属性赋值,所以要使用上面的代码,依赖注入sessionFactory,而这个sessionFactory在spring配置文件里已经定义了。所以在部署启动服务器的时候就会初始化这个sessionFactory然后赋值给给这个属性。
这里的工作已经做的差不多了,后面实现各个对象的访问层类的编写就很容易多了。
public interface IUserDao extends ICommonDao<User>{
public final static String SERVICE_NAME = "cn.water.cf.dao.impl.UserDaoImpl";
}
@Repository(IUserDao.SERVICE_NAME)
public class UserDaoImpl extends CommonDaoImpl<User> implements IUserDao{
}
从上面的代码可以看出,UserDaoImpl里面什么代码都不用写,因为他已经继承了CommonDaoImpl这个类,并通过泛型User传递进去,所以,直接调用父类的增删改查的方法就可以对数据库中User表的数据进行操作。