Struts2 + Spring + Hibernate 通用 Service 和 DAO

时间:2023-03-08 17:37:55

我在 Struts2 + Spring + Hibernate  项目开发中总结出了一个Service 和 DAO ,可以用于处理任何的pojo(bean)。使用这两个Service 和 DAO 可以极大地提高开发的效率,不必再分别针对不同的pojo编写对应的Service 和 DAO。内容如下:

DAO:

接口:BaseDao.java

package dao;

import java.util.List;

/**
* @author 雷霄骅
* 对Object的DAO操作
* 提供了通用的一些方法
*/ public interface BaseDao {
public void save(Object object);
public void delete(Object object);
public void update(Object object);
public Object ReadSingle(String targetName,String propertyName,Object value);
public List<Object> ReadByProperty(String targetName,String propertyName,Object value);
public List<Object> ReadAll(String targetName);
public List<Object> ReadAllByOrder(String targetName,String propertyName,String order);
public Object get(int id);
public List<Object> ReadByPropertyList(String targetName,List<String> propertyName, List<Object> value);
public Integer ReadCount(String targetName);
public List<Object> ReadLimitedByOrder(String targetName, String propertyName,int num, String order);
}

实现:BaseDaoImpl.java

package dao;

import java.sql.SQLException;
import java.util.List; import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport; /**
* @author 雷霄骅
* HibernateTemplate提供非常多的常用方法来完成基本的操作,比如通常的增加、删除、修改、查询等操作,
* Spring 2.0更增加对命名SQL查询的支持,也增加对分页的支持。大部分情况下,就可完成大多数DAO对象的CRUD操作。
*/
public class BaseDaoImpl extends HibernateDaoSupport implements BaseDao{ @Override
public void save(Object object) {
getHibernateTemplate().save(object);
//System.out.println("save "+object.toString());
} @Override
public void delete(Object object) {
getHibernateTemplate().delete(object);
} @Override
public void update(Object object) {
getHibernateTemplate().update(object);
//改用saveOrUpdate,在评价的时候,第一次创建的时候Save,其他时候Update
//getHibernateTemplate().saveOrUpdate(object);
//System.out.println("update "+object.toString());
} @SuppressWarnings("unchecked")
@Override
public Object ReadSingle(final String targetName,final String propertyName, final Object value) {
// TODO Auto-generated method stub
return (Object) getHibernateTemplate().execute(new HibernateCallback() {
/*doInHibernate()。session的创建和销毁,一切都在程序内部完成。*/
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
String hql = "from "+targetName+" as "+targetName+" where "+targetName+"." + propertyName + "=:value";
Query query = session.createQuery(hql);
query.setParameter("value", value);
return query.uniqueResult();
}
});
} @SuppressWarnings("unchecked")
@Override
public List<Object> ReadAll(String targetName) {
// TODO Auto-generated method stub
String hql="from "+targetName;
return getHibernateTemplate().find(hql);
} @SuppressWarnings("unchecked")
@Override
public List<Object> ReadByProperty(final String targetName, final String propertyName,
final Object value) {
// TODO Auto-generated method stub
return (List<Object>) getHibernateTemplate().execute(new HibernateCallback() {
/*doInHibernate()。session的创建和销毁,一切都在程序内部完成。*/
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
String hql = "from "+targetName+" as "+targetName+" where "+targetName+"." + propertyName + "=:value";
Query query = session.createQuery(hql);
query.setParameter("value", value);
return query.list();
}
});
}
//比ReadByProperty简单很多
@Override
public Object get(int id) {
// TODO Auto-generated method stub
return getHibernateTemplate().get(Object.class, id);
} @Override
public List<Object> ReadByPropertyList(final String targetName,
final List<String> propertyName, final List<Object> value) {
// TODO Auto-generated method stub
return (List<Object>) getHibernateTemplate().execute(new HibernateCallback() {
/*doInHibernate()。session的创建和销毁,一切都在程序内部完成。*/
public Object doInHibernate(Session session) throws HibernateException, SQLException {
String hql = "from "+targetName+" as "+targetName; //-------------------------------
for(int i=0;i<propertyName.size();i++){
String propertynametemp= propertyName.get(i);
Object propertyvaluetemp= value.get(i);
if(propertynametemp!=null){
if(i==0){
hql=hql+" where "+targetName+"." + propertynametemp + "=" + propertyvaluetemp +" ";
}else{
hql=hql+" and "+targetName+"." +propertynametemp + "=" + propertyvaluetemp +" ";
}
}
}
//-------------------------------
Query query = session.createQuery(hql);
//当返回的数据不是一条的时候,不用uniqueresult(),而用list()
return query.list();
}
});
}
//这里在Hibernate2.0之前版本list.get(0)返回的是Integer类型.
//但是在Hibernate3.0以后版本list.get(0)返回的是Long类型.
//所以在这里不可以由Long型强转成Integer类型.
//Integer属于不可更改类型,而且Long和Integer没有任何继承关系,当然不能这样转换。
@Override
public Integer ReadCount(final String targetName) {
// TODO Auto-generated method stub
return (Integer) getHibernateTemplate().execute(new HibernateCallback() {
/*doInHibernate()。session的创建和销毁,一切都在程序内部完成。*/
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
String hql = "select count(*) from "+targetName;
//System.out.println(hql);
//注:java.lang.Number是Integer,Long的父类.
return ((Number)session.createQuery(hql).iterate().next()).intValue();
}
});
} @Override
public List<Object> ReadLimitedByOrder(final String targetName,
final String propertyName, final int num, final String order) {
// TODO Auto-generated method stub
return (List<Object>) getHibernateTemplate().execute(new HibernateCallback() {
/*doInHibernate()。session的创建和销毁,一切都在程序内部完成。*/
public Object doInHibernate(Session session) throws HibernateException, SQLException {
String hql ="from "+targetName+" as "+targetName+ " order by "+targetName+"." + propertyName+ " " + order;
Query query = session.createQuery(hql);
query.setMaxResults(num);
//当返回的数据不是一条的时候,不用uniqueresult(),而用list()
return query.list();
}
});
} @Override
public List<Object> ReadAllByOrder(String targetName, String propertyName,
String order) {
// TODO Auto-generated method stub
String hql="from "+targetName+" as "+targetName+ " order by "+targetName+"." + propertyName+ " " + order;
return getHibernateTemplate().find(hql);
} }

Service:

接口:BaseService.java

package service;

import java.util.List;

/**
* @author 雷霄骅
* 对Object的Service
* 提供了一些通用的方法
*/
public interface BaseService {
public void save(Object object);
public void update(Object object);
public void delete(Object object);
public Object ReadByID(String targetName,int id);
@SuppressWarnings("rawtypes")
public List ReadAll(String targetName);
public List ReadAllByOrder(String targetName,String propertyName,String order);
@SuppressWarnings("rawtypes")
public List ReadByProperty(String targetName,String propertyName,Object propertyValue);
public List ReadByPropertyList(String targetName,List<String> propertyName,List<Object> propertyValue);
public List ReadLimitedByOrder(String targetName,String propertyName,int num,String order);
public Object ReadSingle(String targetName,String propertyName,Object propertyValue);
public int ReadCount(String targetName); }

实现:BaseServiceImpl.java

package service;

import java.util.ArrayList;
import java.util.List; import dao.BaseDao;
/**
* @author 雷霄骅
* 对Object的Service
* 提供了一些通用的方法
*/
public class BaseServiceImpl implements BaseService { private BaseDao baseDao;
@Override
public void save(Object object) {
// TODO Auto-generated method stub
baseDao.save(object);
} @Override
public void update(Object object) {
// TODO Auto-generated method stub
baseDao.update(object);
} @Override
public void delete(Object object) {
// TODO Auto-generated method stub
baseDao.delete(object);
} @Override
public Object ReadByID(String targetName,int id) {
// TODO Auto-generated method stub
return baseDao.ReadSingle(targetName,"id", id);
} @SuppressWarnings("rawtypes")
@Override
public List ReadAll(String targetName) {
// TODO Auto-generated method stub
return baseDao.ReadAll(targetName);
} @SuppressWarnings("rawtypes")
@Override
public List ReadAllByOrder(String targetName,String propertyName,String order) {
// TODO Auto-generated method stub
return baseDao.ReadAllByOrder(targetName,propertyName,order);
} public BaseDao getBaseDao() {
return baseDao;
} public void setBaseDao(BaseDao baseDao) {
this.baseDao = baseDao;
} @Override
public List ReadByProperty(String targetName, String propertyName,
Object propertyValue) {
// TODO Auto-generated method stub
return baseDao.ReadByProperty(targetName, propertyName, propertyValue);
} @Override
public Object ReadSingle(String targetName, String propertyName,
Object propertyValue) {
// TODO Auto-generated method stub
return baseDao.ReadSingle(targetName, propertyName, propertyValue);
} @Override
public int ReadCount(String targetName) {
// TODO Auto-generated method stub
return baseDao.ReadCount(targetName);
} @Override
public List ReadLimitedByOrder(String targetName, String propertyName,
int num, String order) {
return baseDao.ReadLimitedByOrder(targetName,propertyName,num,order);
} @Override
public List ReadByPropertyList(String targetName,
List<String> propertyName, List<Object> propertyValue) {
// TODO Auto-generated method stub
return baseDao.ReadByPropertyList(targetName,propertyName,propertyValue);
} }

这样,在Action层调用方法的时候,可以直接调用BaseService相应的方法完成操作。

举一个例子:

有这么一个名字叫Blog的pojo:

package bean;

import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table; /**
* Blog entity. @author MyEclipse Persistence Tools
*/
@Entity
@Table(name = "blog", catalog = "vqe")
public class Blog implements java.io.Serializable { // Fields private Integer id;
private Admin admin;
private String title;
private Timestamp modifytime;
private String content; // Constructors /** default constructor */
public Blog() {
} /** full constructor */
public Blog(Admin admin, String title, Timestamp modifytime, String content) {
this.admin = admin;
this.title = title;
this.modifytime = modifytime;
this.content = content;
} // Property accessors
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
} public void setId(Integer id) {
this.id = id;
} @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "adminid")
public Admin getAdmin() {
return this.admin;
} public void setAdmin(Admin admin) {
this.admin = admin;
} @Column(name = "title", length = 200)
public String getTitle() {
return this.title;
} public void setTitle(String title) {
this.title = title;
} @Column(name = "modifytime", length = 19)
public Timestamp getModifytime() {
return this.modifytime;
} public void setModifytime(Timestamp modifytime) {
this.modifytime = modifytime;
} @Column(name = "content", length = 10000)
public String getContent() {
return this.content;
} public void setContent(String content) {
this.content = content;
} }

该类代表博客的一篇文章。

在Action层只需调用BaeService对应的方法就能完成相应的操作。换句话说,只要把pojo的类的名字当一个字符串传递给ReadByID这种的函数,就可以实现相应的功能。

//根据ID读取:
Blog blog=(Blog) baseService.ReadByID("Blog", blogid);
//添加:
baseService.save(blog);
//修改:
baseService.update(blog);
//删除:
baseService.delete(blog);
//读取所有(根据时间降序)
List<Blog> resultblog=baseService.ReadAllByOrder("Blog","modifytime","desc");
//读取num条(根据时间降序)
List<Blog> resultblog=baseService.ReadLimitedByOrder("Blog","modifytime",num,"desc");

完整的实现Blog(博客)的增删改查的Action示例:

package action;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Map; import service.BaseService; import bean.Admin;
import bean.Blog; import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* @author 雷霄骅
* Action
*/
public class BlogAct extends ActionSupport {
private int blogid;
private int num;
private Blog blog;
private List<Blog> resultblog;
private BaseService baseService; public int getBlogid() {
return blogid;
} public void setBlogid(int blogid) {
this.blogid = blogid;
} public Blog getBlog() {
return blog;
} public void setBlog(Blog blog) {
this.blog = blog;
} public BaseService getBaseService() {
return baseService;
} public void setBaseService(BaseService baseService) {
this.baseService = baseService;
} public List<Blog> getResultblog() {
return resultblog;
} public void setResultblog(List<Blog> resultblog) {
this.resultblog = resultblog;
} public int getNum() {
return num;
} public void setNum(int num) {
this.num = num;
} public String Add(){
try{
//--------------------------------
ActionContext context = ActionContext.getContext();
Map sessionMap = context.getSession();
Admin admin=(Admin)sessionMap.get("admin");
//--------------------------------
blog.setModifytime( new Timestamp(new Date().getTime()));
blog.setAdmin(admin);
baseService.save(blog);
return SUCCESS;
}
catch(Exception ex){
ex.printStackTrace();
return ERROR;
}
} public String Delete(){
try{
blog=(Blog) baseService.ReadByID("Blog", blogid);
baseService.delete(blog);
return SUCCESS;
}
catch(Exception ex){
ex.printStackTrace();
return ERROR;
}
} public String Read(){
try{
blog=(Blog) baseService.ReadByID("Blog", blogid);
return SUCCESS;
}
catch(Exception ex){
ex.printStackTrace();
return ERROR;
}
} public String Update(){
try{
//--------------------------------
ActionContext context = ActionContext.getContext();
Map sessionMap = context.getSession();
Admin admin=(Admin)sessionMap.get("admin");
//--------------------------------
blog.setModifytime( new Timestamp(new Date().getTime()));
blog.setAdmin(admin);
baseService.update(blog);
return SUCCESS;
}
catch(Exception ex){
ex.printStackTrace();
return ERROR;
}
} public String ReadAll(){
try{
resultblog=baseService.ReadAllByOrder("Blog","modifytime","desc");
return SUCCESS;
}
catch(Exception ex){
ex.printStackTrace();
return ERROR;
}
} public String ReadLimitedByOrder(){
try{
resultblog=baseService.ReadLimitedByOrder("Blog","modifytime",num,"desc");
return SUCCESS;
}
catch(Exception ex){
ex.printStackTrace();
return ERROR;
}
}
}