表现层和持久层的代码抽取

 

通过在表现层和持久层实现编写代码抽取类,可以减少不必要的重复代码编写工作。

具体实现如下图

 

(一)持久层baseDao

import java.io.Serializable;
import java.util.List;

import org.hibernate.criterion.DetachedCriteria;

import com.itheima.bos.utils.PageBean;

/**
* 持久层通用接口
* @author zhaoqx
*
* @param <T>
*/
public interface IBaseDao<T> {
public void save(T entity);
public void delete(T entity);
public void update(T entity);
public void saveOrUpdate(T entity);
public T findById(Serializable id);
public List<T> findAll();
public List<T> findByCriteria(DetachedCriteria detachedCriteria);
public void executeUpdate(String queryName,Object...objects);
public void pageQuery(PageBean pageBean);
}

baseDaoImpl实现

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.itheima.bos.dao.base.IBaseDao;
import com.itheima.bos.utils.PageBean;
/**
* 持久层通用实现
* @author zhaoqx
*
* @param <T>
*/
public class BaseDaoImpl<T> extends HibernateDaoSupport implements IBaseDao<T> {
//代表的是某个实体的类型
private Class<T> entityClass;

@Resource//根据类型注入spring工厂中的会话工厂对象sessionFactory
public void setMySessionFactory(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}

//在父类(BaseDaoImpl)的构造方法中动态获得entityClass
public BaseDaoImpl() {
ParameterizedType superclass = (ParameterizedType) this.getClass().getGenericSuperclass();
//获得父类上声明的泛型数组
Type[] actualTypeArguments = superclass.getActualTypeArguments();
entityClass = (Class<T>) actualTypeArguments[0];
}

public void save(T entity) {
this.getHibernateTemplate().save(entity);
}

public void delete(T entity) {
this.getHibernateTemplate().delete(entity);
}

public void update(T entity) {
this.getHibernateTemplate().update(entity);
}

public T findById(Serializable id) {
return this.getHibernateTemplate().get(entityClass, id);
}

public List<T> findAll() {
String hql = "FROM " + entityClass.getSimpleName();//注意from 后要加空格
return (List<T>) this.getHibernateTemplate().find(hql);
}

//执行更新
public void executeUpdate(String queryName, Object... objects) {
Session session = this.getSessionFactory().getCurrentSession();
Query query = session.getNamedQuery(queryName);
int i = 0;
for (Object object : objects) {
//为HQL语句中的?赋值
query.setParameter(i++, object);
}
//执行更新
query.executeUpdate();
}

/**
* 通用分页查询方法
*/
public void pageQuery(PageBean pageBean) {
int currentPage = pageBean.getCurrentPage();
int pageSize = pageBean.getPageSize();
DetachedCriteria detachedCriteria = pageBean.getDetachedCriteria();

//查询total---总数据量
detachedCriteria.setProjection(Projections.rowCount());//指定hibernate框架发出sql的形式----》select count(*) from bc_staff;
List<Long> countList = (List<Long>) this.getHibernateTemplate().findByCriteria(detachedCriteria);
Long count = countList.get(0);
pageBean.setTotal(count.intValue());

//查询rows---当前页需要展示的数据集合
detachedCriteria.setProjection(null);//指定hibernate框架发出sql的形式----》select * from bc_staff;
//指定hibernate框架封装对象的方式
detachedCriteria.setResultTransformer(DetachedCriteria.ROOT_ENTITY);
int firstResult = (currentPage - 1) * pageSize;
int maxResults = pageSize;
List rows = this.getHibernateTemplate().findByCriteria(detachedCriteria, firstResult, maxResults);
pageBean.setRows(rows);
}

public void saveOrUpdate(T entity) {
this.getHibernateTemplate().saveOrUpdate(entity);
}

public List<T> findByCriteria(DetachedCriteria detachedCriteria) {
return (List<T>) this.getHibernateTemplate().findByCriteria(detachedCriteria);
}
}

注意点

1、泛型的获取

在实现了BaseDao接口后,因为在查询数据库时要用到传入的泛型类型T,所以我们可以使用方法获取传入的的泛型T,T在运行期的时候已经知道类型。

因为,在构建子类对象的时候,父类的构造方法会被调用,所以可以在BaseDaoImpl里获取泛型类型。

ParameterizedType pt = 
(ParameterizedType)this.getClass().getGenericSuperclass(); 
这里的this表示继承该类的子类对象,这个语句的意思是获取带参数的BaseDaoImpl的完整类名,

然后 (Class< T >)pt.getActualTypeArguments()[0]获取参数类型。

2、sessionfactory的注入

@Resource
public void setMySessionFactory(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}

因为以前的配置式的话,在dao的<bean>配置里会注入sessionfactory,如<property="" ref="">,

然后观察类HibernateDaoSupport的源码,

发现,其构建模板对象需要注入sessionfactory,而我们现在使用的是注解开发,又因为该类是final,不能被覆写,

所以我们只能另外写一个类,在里面调用模板类的setSessiobfactory方法来构建模板对象,使用@Resource来注入

sessionFactory对象。

(二)表现层BaseAction

开发模型

 

BaseAction

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.apache.struts2.ServletActionContext;
import org.hibernate.criterion.DetachedCriteria;

import com.itheima.bos.domain.Staff;
import com.itheima.bos.utils.PageBean;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
/**
* 表现层通用实现
* @author zhaoqx
*
* @param <T>
*/
public class BaseAction<T> extends ActionSupport implements ModelDriven<T> {
protected PageBean pageBean = new PageBean();
//创建离线提交查询对象
DetachedCriteria detachedCriteria = null;

public void setPage(int page) {
pageBean.setCurrentPage(page);
}

public void setRows(int rows) {
pageBean.setPageSize(rows);
}

/**
* 将指定Java对象转为json,并响应到客户端页面
* @param o
* @param exclueds
*/
public void java2Json(Object o ,String[] exclueds){
JsonConfig jsonConfig = new JsonConfig();
//指定哪些属性不需要转json
jsonConfig.setExcludes(exclueds);
String json = JSONObject.fromObject(o,jsonConfig).toString();
ServletActionContext.getResponse().setContentType("text/json;charset=utf-8");
try {
ServletActionContext.getResponse().getWriter().print(json);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 将指定Java对象转为json,并响应到客户端页面
* @param o
* @param exclueds
*/
public void java2Json(List o ,String[] exclueds){
JsonConfig jsonConfig = new JsonConfig();
//指定哪些属性不需要转json
jsonConfig.setExcludes(exclueds);
String json = JSONArray.fromObject(o,jsonConfig).toString();
ServletActionContext.getResponse().setContentType("text/json;charset=utf-8");
try {
ServletActionContext.getResponse().getWriter().print(json);
} catch (IOException e) {
e.printStackTrace();
}
}

public static final String HOME = "home";
public static final String LIST = "list";

//模型对象
protected T model;
public T getModel() {
return model;
}

//在构造方法中动态获取实体类型,通过反射创建model对象
public BaseAction() {
ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
//获得BaseAction上声明的泛型数组
Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments();
Class<T> entityClass = (Class<T>) actualTypeArguments[0];
detachedCriteria = DetachedCriteria.forClass(entityClass);
pageBean.setDetachedCriteria(detachedCriteria);
//通过反射创建对象
try {
model = entityClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

1、model对象类型T的获取

ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
//获得BaseAction上声明的泛型数组
Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments();
Class<T> entityClass = (Class<T>) actualTypeArguments[0];

actualTypeArguments[0]代表*.class,所以还要通过反射获取实例。

model = entityClass.newInstance();

 

posted on 2018-11-21 12:36  有杏何须梅  阅读(318)  评论(0)    收藏  举报

导航