六、定义基本类
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; } }
(待续)