六、定义基本类
1)定义Action基本类-主要定义request,session等
BaseAction.java
package ssh.base;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
public class BaseAction extends ActionSupport implements RequestAware,SessionAware, ApplicationAware,ServletResponseAware{
private static final long serialVersionUID = 4818541693118631758L;
public Map<String, Object> request; //一般少用,因为value stack里就是request
public Map<String, Object> session;
public Map<String, Object> application;//基本不用。可以放数据库或者放在一个CLASS里面
public HttpServletResponse response;
//ServletActionContext.getRequest()同样也可以直接去的request
public void setRequest(Map<String, Object> request) {
this.request=request;
}
public void setSession(Map<String, Object> session) {
this.session=session;
}
public void setApplication(Map<String, Object> application) {
this.application=application;
}
public void setServletResponse(HttpServletResponse response) {
this.response=response;
}
}
2)定义接口DAO类,主要定义CURD,分页等基本相同的接口
DAO.java
package ssh.base;
import java.util.LinkedHashMap;
import ssh.utils.QueryResult;
public interface DAO {
//保存数据
public void save(Object entity);
//更新数据
public void update(Object entity);
//删除单条记录
public <T> void delete(Class<T> entityClass,Object entityId);
//删除多条记录
public <T> void delete(Class<T> entityClass,Object[] entityIds);
//查找指定ID的实体类数据
public <T> T find(Class<T> entityClass,Object entityId); //在方法上定义泛型需要在方法上写<X>,,第一个T是定义泛型,第2个T是返回类型
/**
* 获得分页数据
* QueryResult<T> 泛型定义在类上。因为需要返回查询的数据List,和查询的总条数,所以需要自定义类型返回2个数据
* @param <T> 泛型
* @param entityClass 实体类
* @param firstIndex 开始索引
* @param maxResult 需要获取的记录数
* @param wherejpql where条件语句
* @param queryParams 条件语句参数
* @param orderby 排序,LinkedHashMap先进先出,使用这个是因为先进去的放到第一位,order by key1 desc,key2 asc
* @return
*/
public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstIndex, int maxResult, String wherejpql,Object[] queryParams,LinkedHashMap<String, String> orderby);
public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstIndex, int maxResult,String wherejpql,Object[] queryParams);
public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstIndex, int maxResult,LinkedHashMap<String, String> orderby);
public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstIndex, int maxResult);
public <T> QueryResult<T> getScrollData(Class<T> entityClass);
}
3)定义实现DAO基本接口的DAOImpl的实现类,供其他实现类直接继承
而且必须写@Component注入给Spring管理,然后注入hibernateTemplate,使用protected,其他类继承后可以直接使用
DaoSupport.java
package ssh.base;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
import javax.annotation.Resource;
import javax.persistence.Entity;
import ssh.utils.QueryResult;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Component;
//定义抽象类继承DAO,抽象出所有实体通用的方法,方便其他类继承就可以了,abstract定义了只能继承。
@Component //放到Spring里,让Spring管理
public abstract class DaoSupport implements DAO {
//注入hibernateTemplate,使用protected,其他类继承后可以直接使用
public HibernateTemplate hibernateTemplate;
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
@Resource //注入hibernateTemplate
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
/**保存数据
* 调用方法:save(new User("shazhuzhu",20)
*/
public void save(Object entity) {
hibernateTemplate.save(entity);
}
/**更新数据
* 调用方法:update(new User(1,"shazhuzhu",20); 其中1为ID
*/
public void update(Object entity) {
hibernateTemplate.update(entity); //把游离状态的实体BENA同步到数据库
}
/**删除单条记录
* 调用方法:delete(User.class,1); 其中1为ID
*/
public <T> void delete(Class<T> entityClass,Object entityid) {
delete(entityClass, new Object[]{entityid}); //调用下面的方法
}
//删除多条记录
public <T> void delete(Class<T> entityClass,Object[] entityids) {
for(Object id:entityids){
T t=find(entityClass,id); 调用下面的find方法先把实体类查找出来,然后在DEL,这样才能通过ID删除数据
if(t!=null) //先判断需要删除的数据是否存在
hibernateTemplate.delete(t);
}
}
/**查询指定ID的记录
* 调用方法:find(User.class,1); 其中1为ID
*/
@SuppressWarnings("unchecked")
public <T> T find(Class<T> entityClass, Object entityId) {
return (T) hibernateTemplate.get(entityClass,(Serializable) entityId);
}
/**
* 获得分页数据
* QueryResult<T> 泛型定义在类上。因为需要返回查询的数据List,和查询的总条数,所以需要自定义类型返回2个数据
* @param <T> 泛型
* @param entityClass 实体类
* @param firstIndex 开始索引 firstIndex和maxResult都为-1时代表不分页
* @param maxResult 需要获取的记录数
* @param wherejpql where条件语句
* @param queryParams 条件语句参数
* @param orderby 排序,LinkedHashMap先进先出,使用这个是因为先进去的放到第一位,order by key1 desc,key2 asc
* @return
*
* 调用方法
* LinkedHashMap<String , String> orderby=new LinkedHashMap<String, String>();
* orderby.put("id", "asc");
* QueryResult<TestVo> qr=testDAO.getScrollData(TestVo.class, 1, 10,"o.name=? and o.title=?",new Object[]{"a","1"},orderby);
* for (TestVo q : qr.getResultlist()) {
* System.out.println(q.getName());
* }
* System.out.println(qr.getTotalrecord());
*/
@SuppressWarnings("unchecked") //不检查类型,不然会有黄色线提示错误。
public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstindex, int maxresult,
String wherejpql,Object[] queryParams,LinkedHashMap<String, String> orderby) {
QueryResult qr = new QueryResult<T>(); //定义保存数据类型
String entityname = getEntityName(entityClass); //获取实体类名称,方法下面定义了
String hql="select o from "+entityname+" o " + (wherejpql==null? "" :"where " + wherejpql) + buildOrderby(orderby);
System.out.println(hql);
qr.setResultlist(getListForPage(hql, firstindex, maxresult, queryParams)); //调用hibernateTemplate的扩张方法进行分页处理
String hql2="select count(o) from "+entityname+" o " + (wherejpql==null? "" :"where " + wherejpql);
Long total=(Long) hibernateTemplate.find(hql2,queryParams).get(0); //查询总记录数
qr.setTotalrecord(total);
return qr;
}
/**
* HibernateTemplate 只支持 .setMaxResults(int) 方法。
* 因此,做 Spring+Hibernate 分页处理要使用到一个接口 org.springframework.orm.hibernate3.HibernateCallback
* 来灵活操作数据库,该接口中有一个未实现的方法 Object doInHibernate (Session session),用以获得并利用 session 进行操作(自动创建、销毁)。
* 分页通用方法
* @param sql HQL查询语句
* @param firstindex 起始记录下标
* @param maxresult 读取记录数
* @return List 结果集
*/
@SuppressWarnings("unchecked")
public List getListForPage(final String hql, final int firstindex, final int maxresult,final Object[] queryParams) {
try {
List list = hibernateTemplate.executeFind(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException,SQLException {
Query query = session.createQuery(hql);
if(firstindex!=-1 && maxresult!=-1){ //方便设置-1时不分页
query.setFirstResult(firstindex);
query.setMaxResults(maxresult);
}
setQueryParams(query, queryParams); //调用下面方法插入where传递过来的参数
return query.list();
}
});
return list;
} catch (RuntimeException re) {
throw re;
}
}
public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstindex, int maxresult,LinkedHashMap<String, String> orderby) {
return getScrollData(entityClass,firstindex,maxresult,null,null,orderby);
}
public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstindex, int maxresult,String wherejpql,Object[] queryParams) {
return getScrollData(entityClass,firstindex,maxresult,wherejpql,queryParams,null);
}
public <T> QueryResult<T> getScrollData(Class<T> entityClass,int firstindex, int maxresult) {
return getScrollData(entityClass,firstindex,maxresult,null,null,null);
}
public <T> QueryResult<T> getScrollData(Class<T> entityClass) {
return getScrollData(entityClass,-1,-1); //主方法定义-1为不分页
}
/**
* 获取实体类的名称
* @param <T>
* @param entityClass
* @return
*/
protected <T> String getEntityName(Class<T> entityClass) {
String entityname=entityClass.getSimpleName(); //如果实体类上面的@Entity(name=xxx)没有指定名称,直接为默认类名称
Entity entity=entityClass.getAnnotation(Entity.class); //获取@Entity注解
if(entity.name()!=null&&!"".equals(entity.name())){ //判断注解的name是否为空
entityname=entity.name();
}
return entityname;
}
/**
* 组装order by语句
* @param orderby
* @return // order by o.key desc,key2 asc
*/
protected String buildOrderby(LinkedHashMap<String, String> orderby){
StringBuffer orderbyql=new StringBuffer("");
if(orderby!=null && orderby.size()>0 ){
orderbyql.append(" order by ");
for(String key:orderby.keySet()){ //取得Map的Key的集合
orderbyql.append("o.").append(key).append(" ").append(orderby.get(key)).append(",");
}
orderbyql.deleteCharAt(orderbyql.length()-1);
}
return orderbyql.toString();
}
/**
* 为Where语句传递参数
* @param query
* @param queryParams
* o.key = ?1 and o.name=?2 这是错误的,JPA的问号索引是从1开始的,而HibernateTemplate是从0开始的,HibernateTemplate执行HQL语句时,HQL的语句中'?'号面是不带数字的
* o.key = ? and o.name=? 正确
*/
protected void setQueryParams(Query query,Object[] queryParams) {
if(queryParams!=null && queryParams.length>0){
for(int i=0;i<queryParams.length;i++){ //JPA的问号索引是从1开始的,而HibernateTemplate是从0开始的
query.setParameter(i, queryParams[i]); //如果是JPA:i+1
}
}
}
}
七、写实体类的接口-继承基本接口DAO
UserDAO.java
package ssh.DAO;
import ssh.base.DAO;
public interface UserDAO extends DAO {
//因为继承了基本接口DAO,基本接口DAO已经定义了CURD和分页功能
}
八、写实体类的实现类-继承基本实现类DAOSupport,并继承UserDAO接口
UserDAOImpl.java
package ssh.DAOImpl;
import org.springframework.stereotype.Component;
import ssh.DAO.UserDAO;
import ssh.base.DaoSupport;
@Component
public class UserDAOImpl extends DaoSupport implements UserDAO {
//基本实现类DaoSupport已经实现基本的CURD和分页功能
}
九、定义Service的实现
1)在类前加入@Component,让spring对其初始化
2)用@Resource把userDAO注入进来
UserService.java
package ssh.service;
import java.util.LinkedHashMap;
import javax.annotation.Resource;
import ssh.utils.QueryResult;
import org.springframework.stereotype.Component;
import ssh.DAO.UserDAO;
import ssh.model.User;
@Component
public class UserService {
private UserDAO userDAO;
public UserDAO getUserDAO() {
return userDAO;
}
@Resource
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void save(User user){
userDAO.save(user);
}
public void update(User user){
userDAO.update(user);
}
public void delete(int id){
userDAO.delete(User.class,id);
}
public User find(int id){
return userDAO.find(User.class, id);
}
/*
* 获取分页数据
*/
public QueryResult<User> getScrollData(int firstindex, int maxresult,String wherejpql,Object[] queryParams,LinkedHashMap<String, String> orderby) {
QueryResult<User> qr=userDAO.getScrollData(User.class, firstindex, maxresult, wherejpql, queryParams, orderby);
return qr;
}
}
(待续)