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() {
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
}
}
}
}