您的位置:首页 > 其它

(project)利用接口,继承,泛型封装dao数据访问层

2015-12-05 14:51 495 查看
一般在建立工程的时候会根据不同的模块的功能来建包,



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: 根据业务层传递的条件和要更新的字段进行局部的更新
* @Auth
4000
or: 张淼洁(作者)
* @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表的数据进行操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  面向对象 泛型 继承