而我们对这些Model的操作很多都是类似的,下面是我举出的一些(见名知意,其它自行脑补):
1.save
2.saveAll
3.findById
4.update
5.saveOrUpdate
6.delete
7.deleteAll
8.deleteById
9.loadAll
10.load(int page,int rows)
11.getTotalCount
12.getScrollData(int firstResult, int maxResult)
13.getScrollData(int firstResult, int maxResult, LinkedHashMap orderby)
14.getScrollData(int firstResult, int maxResult, String where, Object[] params)
15.getScrollData(int firstResult, int maxResult, String where, Object[] params, LinkedHashMap orderby)
如果我们在每个Dao(DaoImpl),Service(ServiceImpl)中都定义这些方法,我们来算一下。假如有20个Model,那么:
20*15*(2+2)= 1200。纳里,这么一堆破东西就花了1200个方法!!!!(下次可以用这个凑代码量了。。。。)平均每个方法实现了20次,平均每个方法复制了不下40次。还要保证不出任何错误,这个还真是个苦力活。下面是我们更先进的方法。【注:次方法必须将Spring更新到4,Spring3还不支持泛型注入!】
我们在Dao(DaoImpl),Service(ServiceImpl)中定义BaseDao(BaseDaoImpl),BaseService(BaseServiceImpl),然后由于ORM使用的是Hibernate,我们在操作一个实体的时候其实只需要知道两个属性{Model.id.class(主键类型),Model.class(实体类类型)},好吧其实都是Class类型,还是可序列化的。这样我们的BaseDao在实现的时候不需要关注具体是哪个实体类,根据Model.id.class和Model.class即可获取操作的一切【那CURD操作来说】。然后每个具体的Dao继承BaseDao,就可以拥有BaseDao中定义的十多个方法(不需重复复制代码),还可以根据业务需求扩展具体Dao中的方法,做到了很大程度的解耦(基础操作和特殊操作的解耦)。然后具体的DaoImpl首先继承自BaseDaoImpl(这样那十多个基础方法的实现就又可以省去了)再实现自己Dao的特殊业务逻辑方法。解耦很到位!【当然既然是基于泛型的那么别传错了Model类!!!】,Service(ServiceImpl)层也是一样的!!!
下面是包的结构:
com.xy.model
{Car,Driver,Passenger}
com.xy.dao
{BaseDao,CarDao,DriverDao,PassengerDao}
com.xy.dao.impl
{BaseDaoImpl,CarDaoImpl,DriverDaoImpl,PassengerDaoImpl}
com.xy.service
{BaseService,CarService,DriverService,PassengerService}
com.xy.service.impl
{BaseServiceImpl,CarServiceImpl,DriverServiceImpl,PassengerServiceImpl}
下面是配置文件信息:【本来觉得这个不是重点,没有必要填上来的,不过还是贴了】
##web.xml
org.springframework.web.context.request.RequestContextListener
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
classpath:spring.xml,classpath:spring-hibernate.xml
org.springframework.web.util.IntrospectorCleanupListener
openSessionInViewFilter
org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
singleSession
true
openSessionInViewFilter
*.action
##Spring.xml
##Spring-hibernate.xml
${hibernate.hbm2ddl.auto}
${hibernate.dialect}
${hibernate.show_sql}
${hibernate.format_sql}
com.xy.model
后面到了重点了!!!
#BaseDao.java
public interface BaseDaoInter {
/**
* 由session工厂获取当前session对象
* @return
*/
public Session getSession();
/**
* 将实体对象保存到数据库中
* @param t 待保存的实体对象
* @return 实体对象的ID
*/
public K save(T t);
/**
* 将实体对象【集合】保存到数据库中
* @param ct 实体对象【集合】
*/
public void saveAll(Collection ct);
/**
* 根据Id查询实体对象
* @param id 表记录中的对应的id字段
* @return 对应的实体对象
*/
public T findById(K id);
/**
* 更新一条记录
* @param t 待更新记录对应的实体对象
* @return 更新后的实体对象
*/
public T update(T t);
/**
* 保存或更新一个实体对象到表记录中
* @param t 待更新的实体对象
* @return 更新后的实体对象
*/
public T saveOrUpdate(T t);
/**
* 删除一个实体对象对应的表记录
* @param t 待删除的实体对象
*/
public void delete(T t);
/**
* 删除一组记录
* @param ct 待删除记录集合
*/
public void deleteAll(Collection ct);
/**
* 根据id删除一条记录
* @param id 待删除记录id
* @return 是否删除成功(id是否有效)
*/
public boolean deleteById(K id);
/**
* 加载所有记录集合
* @return 所有记录集合
*/
public QueryResult loadAll();
/**
* 分页加载记录集合
* @param page 当前第多少页
* @param rows 每页最多多少行数据
* @return 第page页的数据集合
*/
public QueryResult load(int page,int rows);
/**
* 获取总记录数
* @return 总数
*/
public long getTotalCount();
/******************************HQL******************************/
/**
* 分页获取所有记录
* @return
*/
public QueryResult getScrollData();
/**
* 分页获取记录
* @param firstResult 开始索引,如果输入值为-1,即获取全部数据
* @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
* @return
*/
public QueryResult getScrollData(int firstResult, int maxResult);
/**
* 分页获取记录
* @param firstResult 开始索引,如果输入值为-1,即获取全部数据
* @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
* @param orderby 排序,Key为排序属性,Value为asc/desc,如:
* LinkedHashMap orderby = new LinkedHashMap();
orderby.put("email", "asc");
orderby.put("password", "desc");
* @return
*/
public QueryResult getScrollData(int firstResult, int maxResult, LinkedHashMap orderby);
/**
* 分页获取记录
* @param firstResult 开始索引,如果输入值为-1,即获取全部数据
* @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
* @param where 条件语句,不带where关键字,条件语句只能使用位置参数,位置参数的索引值以1开始,如:o.username=?1 and o.password=?2
* @param params 条件语句出现的位置参数值
* @return
*/
public QueryResult getScrollData(int firstResult, int maxResult, String where, Object[] params);
/**
* 分页获取记录
* @param firstResult 开始索引,如果输入值为-1,即获取全部数据
* @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
* @param where 条件语句,不带where关键字,条件语句只能使用位置参数,位置参数的索引值以1开始,如:o.username=?1 and o.password=?2
* @param params 条件语句出现的位置参数值
* @param orderby 排序,Key为排序属性,Value为asc/desc,如:
* LinkedHashMap orderby = new LinkedHashMap();
orderby.put("email", "asc");
orderby.put("password", "desc");
* @return
*/
public QueryResult getScrollData(int firstResult, int maxResult, String where, Object[] params, LinkedHashMap orderby);
}
public interface CarDaoInter extends BaseDaoInter{
}
public interface DriverDaoInter extends BaseDaoInter,Driver>{
}
#BaseDaoImpl.java
/**
* 不一定必须是abstract类型的, 请不要对BaseDaoImpl使用@Repository注解,因为无法直接指定clatt属性值
* class值由继承类来指定
*
* @author BearSmall
*
* @param
*/
public abstract class BaseDaoImpl
implements BaseDaoInter {
@Autowired
private SessionFactory sessionFactory; // 从容器中注入session工厂【无需get,set方法】
private Class clatt; // 【实体类对应的Class对象】
/**
* //向子类暴露的接口获用来获取sessionFactory
*
* @return sessionFactory
*/
public SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* 保留指定clatt值的接口【通过子类显示调用父类的构造函数来指定】
*
* @param clatt
*/
public BaseDaoImpl(Class clatt) {
this.clatt = clatt;
}
// @SuppressWarnings("unchecked")
// public BaseDaoImpl() {//另外一种方式指定clatt值,要求类必须是abstract类型
// ParameterizedType parameterizedType =
// (ParameterizedType)this.getClass().getGenericSuperclass();
// clatt= (Class)(parameterizedType.getActualTypeArguments()[0]);
// }
@Override
public Session getSession() {
return getSessionFactory().getCurrentSession();
}
@SuppressWarnings("unchecked")
@Override
public K save(T t) {
Session session = getSession();
return (K) session.save(t);
}
@Override
public T findById(K id) {
Session session = getSession();
@SuppressWarnings("unchecked")
T t = (T) session.get(clatt, id);
return t;
}
@Override
public void saveAll(Collection ct) {
Session session = getSession();
for (T t : ct) {
session.save(t);
}
}
@Override
public T update(T t) {
Session session = getSession();
session.update(t);
return t;
}
@Override
public void deleteAll(Collection ct) {
Session session = getSession();
for (T t : ct) {
session.delete(t);
}
}
@Override
public T saveOrUpdate(T t) {
Session session = getSession();
session.saveOrUpdate(t);
return t;
}
@Override
public void delete(T t) {
Session session = getSession();
session.delete(t);
}
@Override
public boolean deleteById(K id) {
Session session = getSession();
@SuppressWarnings("unchecked")
T t = (T) session.get(clatt, id);
if (t == null)
return false;
session.delete(t);
return true;
}
@SuppressWarnings("unchecked")
@Override
public QueryResult loadAll() {
Session session = getSession();
Criteria criteria = session.createCriteria(clatt);
QueryResult result = new QueryResult<>();
result.setDatas(criteria.list());
result.setTotalCount(Long.parseLong(criteria
.setProjection(Projections.rowCount()).uniqueResult()
.toString()));
return result;
}
@SuppressWarnings("unchecked")
@Override
public QueryResult load(int page, int rows) {
Session session = getSession();
Criteria criteria = session.createCriteria(clatt);
criteria.setFirstResult((page - 1) * rows);
criteria.setMaxResults(rows);
QueryResult result = new QueryResult<>();
result.setDatas(criteria.list());
result.setTotalCount(Long.parseLong(criteria
.setProjection(Projections.rowCount()).uniqueResult()
.toString()));
return result;
}
@Override
public long getTotalCount() {
Session session = getSession();
Criteria criteria = session.createCriteria(clatt);
Object object = criteria.setProjection(Projections.rowCount())
.uniqueResult();
long totalCount = 0;
if (object != null) {
totalCount = Long.parseLong(object.toString());
}
return totalCount;
}
/****************************** HQL ******************************/
@Override
public QueryResult getScrollData() {
return getScrollData(-1, -1, null, null, null);
}
@Override
public QueryResult getScrollData(int firstResult, int maxResult) {
return getScrollData(firstResult, maxResult, null, null, null);
}
@Override
public QueryResult getScrollData(int firstResult, int maxResult,
LinkedHashMap orderby) {
return getScrollData(firstResult, maxResult, null, null, orderby);
}
@Override
public QueryResult getScrollData(int firstResult, int maxResult,
String where, Object[] params) {
return getScrollData(firstResult, maxResult, where, params, null);
}
@Override
@SuppressWarnings("unchecked")
public QueryResult getScrollData(int firstResult, int maxResult,
String where, Object[] params, LinkedHashMap orderby) {
String entityName = clatt.getSimpleName();
String whereql = where != null && !"".equals(where.trim()) ? " where "
+ where : "";
Session session = getSession();
Query query = session.createQuery("select o from " + entityName + " o"
+ whereql + buildOrderby(orderby));
if (firstResult != -1 && maxResult != -1)
query.setFirstResult(firstResult).setMaxResults(maxResult);
setQueryParameter(query, params);
QueryResult qr = new QueryResult();
// qr.setResultlist(query.getResultList());
Query queryCount = session.createQuery("select count(o) from "
+ entityName + " o" + whereql);
setQueryParameter(queryCount, params);
long count = (Long) queryCount.uniqueResult();
qr.setTotalCount(count);
qr.setDatas(query.list());
return qr;
}
/**
* 设置查询参数
*
* @param query
* 查询对象
* @param params
* 参数值
*/
public static void setQueryParameter(Query query, Object[] params) {
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
}
/**
* 构建排序语句
*
* @param orderby
* 排序属性与asc/desc, Key为属性,Value为asc/desc
* @return
*/
public static String buildOrderby(LinkedHashMap orderby) {
StringBuilder sb = new StringBuilder();
if (orderby != null && !orderby.isEmpty()) {
sb.append(" order by ");
for (Map.Entry entry : orderby.entrySet()) {
sb.append("o.").append(entry.getKey()).append(" ")
.append(entry.getValue()).append(',');
}
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
}
@Repository("carDao")
public class CarDaoImpl extends BaseDaoImpl implements CarDaoInter{
//通过调用父类的构造函数指定clazz值,即实体类的类类型
public CarDaoImpl() {
super(Car.class);
}
}
@Repository(value="driverDao")
public class DriverDaoImpl extends BaseDaoImpl implements DriverDaoInter{
//通过调用父类的构造函数指定clazz值,即实体类的类类型
public DriverDaoImpl() {
super(Driver.class);
}
}
#CarService.java
public interface CarServiceInter extends BaseServiceInter{
}
public interface DriverServiceInter extends BaseServiceInter{
}
@Transactional(propagation=Propagation.REQUIRED)
public abstract class BaseServiceImpl implements BaseServiceInter {
@Autowired
private BaseDaoInter baseDao; //从容器中注入session工厂【无需get,set方法】
@Override
public K save(T t) {
return baseDao.save(t);
}
@Override
public void saveAll(Collection ct) {
baseDao.saveAll(ct);
}
@Override
public T findById(K id) {
return baseDao.findById(id);
}
@Override
public T update(T t) {
return baseDao.update(t);
}
@Override
public T saveOrUpdate(T t) {
return baseDao.saveOrUpdate(t);
}
@Override
public void delete(T t) {
baseDao.delete(t);
}
@Override
public void deleteAll(Collection ct) {
baseDao.deleteAll(ct);
}
@Override
public boolean deleteById(K id) {
return baseDao.deleteById(id);
}
@Override
public QueryResult loadAll() {
return baseDao.loadAll();
}
@Override
public QueryResult load(int page, int rows) {
return baseDao.load(page, rows);
}
@Override
public long getTotalCount() {
return baseDao.getTotalCount();
}
/******************************HQL******************************/
@Override
public QueryResult getScrollData() {
return baseDao.getScrollData();
}
@Override
public QueryResult getScrollData(int firstResult, int maxResult) {
return baseDao.getScrollData(firstResult, maxResult);
}
@Override
public QueryResult getScrollData(int firstResult, int maxResult,
LinkedHashMap orderby) {
return baseDao.getScrollData(firstResult, maxResult, orderby);
}
@Override
public QueryResult getScrollData(int firstResult, int maxResult,
String where, Object[] params) {
return baseDao.getScrollData(firstResult, maxResult, where, params);
}
@Override
public QueryResult getScrollData(int firstResult, int maxResult,
String where, Object[] params, LinkedHashMap orderby) {
return baseDao.getScrollData(firstResult, maxResult, where, params, orderby);
}
}
#BaseService
public interface BaseServiceInter {
/**
* 将实体对象保存到数据库中
* @param t 待保存的实体对象
* @return 实体对象的ID
*/
public K save(T t);
/**
* 将实体对象【集合】保存到数据库中
* @param ct 实体对象【集合】
*/
public void saveAll(Collection ct);
/**
* 根据Id查询实体对象
* @param id 表记录中的对应的id字段
* @return 对应的实体对象
*/
public T findById(K id);
/**
* 更新一条记录
* @param t 待更新记录对应的实体对象
* @return 更新后的实体对象
*/
public T update(T t);
/**
* 保存或更新一个实体对象到表记录中
* @param t 待更新的实体对象
* @return 更新后的实体对象
*/
public T saveOrUpdate(T t);
/**
* 删除一个实体对象对应的表记录
* @param t 待删除的实体对象
*/
public void delete(T t);
/**
* 删除一组记录
* @param ct 待删除记录集合
*/
public void deleteAll(Collection ct);
/**
* 根据id删除一条记录
* @param id 待删除记录id
* @return 是否删除成功(id是否有效)
*/
public boolean deleteById(K id);
/**
* 加载所有记录集合
* @return 所有记录集合
*/
public QueryResult loadAll();
/**
* 分页加载记录集合
* @param page 当前第多少页
* @param rows 每页最多多少行数据
* @return 第page页的数据集合
*/
public QueryResult load(int page,int rows);
/**
* 获取总记录数
* @return 总数
*/
public long getTotalCount();
/******************************HQL******************************/
/**
* 分页获取所有记录
* @return
*/
public QueryResult getScrollData();
/**
* 分页获取记录
* @param firstResult 开始索引,如果输入值为-1,即获取全部数据
* @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
* @return
*/
public QueryResult getScrollData(int firstResult, int maxResult);
/**
* 分页获取记录
* @param firstResult 开始索引,如果输入值为-1,即获取全部数据
* @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
* @param orderby 排序,Key为排序属性,Value为asc/desc,如:
* LinkedHashMap orderby = new LinkedHashMap();
orderby.put("email", "asc");
orderby.put("password", "desc");
* @return
*/
public QueryResult getScrollData(int firstResult, int maxResult, LinkedHashMap orderby);
/**
* 分页获取记录
* @param firstResult 开始索引,如果输入值为-1,即获取全部数据
* @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
* @param where 条件语句,不带where关键字,条件语句只能使用位置参数,位置参数的索引值以1开始,如:o.username=?1 and o.password=?2
* @param params 条件语句出现的位置参数值
* @return
*/
public QueryResult getScrollData(int firstResult, int maxResult, String where, Object[] params);
/**
* 分页获取记录
* @param firstResult 开始索引,如果输入值为-1,即获取全部数据
* @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
* @param where 条件语句,不带where关键字,条件语句只能使用位置参数,位置参数的索引值以1开始,如:o.username=?1 and o.password=?2
* @param params 条件语句出现的位置参数值
* @param orderby 排序,Key为排序属性,Value为asc/desc,如:
* LinkedHashMap orderby = new LinkedHashMap();
orderby.put("email", "asc");
orderby.put("password", "desc");
* @return
*/
public QueryResult getScrollData(int firstResult, int maxResult, String where, Object[] params, LinkedHashMap orderby);
}
@Service("carProxy")
public class CarServiceImpl extends BaseServiceImpl implements CarServiceInter {
@Autowired
private CarDaoInter carDao; //从容器中注入session工厂【无需get,set方法】
}
@Service("driverProxy")
public class DriverServiceImpl extends BaseServiceImpl implements DriverServiceInter {
@Autowired
private DriverDaoInter driverDao; //从容器中注入session工厂【无需get,set方法】
}