基于Spring4+Hibernate4的通用数据访问层+业务逻辑层(Dao层+Service层)设计与实现!

基于泛型的依赖注入。当我们的项目中有很多的Model时,相应的Dao(DaoImpl),Service(ServiceImpl)也会增多。

而我们对这些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<String, String> orderby)
14.getScrollData(int firstResult, int maxResult, String where, Object[] params)
15.getScrollData(int firstResult, int maxResult, String where, Object[] params, LinkedHashMap<String, String> 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

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring.xml,classpath:spring-hibernate.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<filter>
    <filter-name>openSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    <init-param>
        <param-name>singleSession</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>openSessionInViewFilter</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>

##Spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">

    <!-- 引入属性文件,config.properties位于src/main/resources目录下 -->
    <context:property-placeholder location="classpath:config.properties" />

    <!-- 自动扫描dao和service包(自动注入) -->
    <context:component-scan base-package="com.xy.dao.**,com.xy.service.**" />

</beans>

##Spring-hibernate.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">

    <!-- 配置数据源 -->
    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc_url}" />
        <property name="username" value="${jdbc_username}" />
        <property name="password" value="${jdbc_password}" />

        <!-- 初始化连接大小 -->
        <property name="initialSize" value="0" />
        <!-- 连接池最大使用连接数量 -->
        <property name="maxActive" value="20" />
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="0" />
        <!-- 获取连接最大等待时间 -->
        <property name="maxWait" value="60000" />

        <property name="validationQuery" value="${validationQuery}" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="testWhileIdle" value="true" />

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000" />

        <!-- 打开removeAbandoned功能 -->
        <property name="removeAbandoned" value="true" />
        <!-- 1800秒,也就是30分钟 -->
        <property name="removeAbandonedTimeout" value="1800" />
        <!-- 关闭abanded连接时输出错误日志 -->
        <property name="logAbandoned" value="true" />

        <!-- 监控数据库 -->
        <!-- <property name="filters" value="stat" /> -->
        <property name="filters" value="mergeStat" />
    </bean>

    <!-- 配置hibernate session工厂 -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <props>
                <!-- web项目启动时是否更新表结构 -->
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <!-- 系统使用的数据库方言,也就是使用的数据库类型 -->
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <!-- 是否打印Hibernate生成的SQL到控制台 -->
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <!-- 是否格式化打印出来的SQL -->
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
            </props>
        </property>
        <!-- 自动扫描注解方式配置的hibernate类文件 -->
        <property name="packagesToScan">
            <list>
                <value>com.xy.model</value>
            </list>
        </property>

        <!-- 自动扫描hbm方式配置的hibernate文件和.hbm文件 -->
        <!--
        <property name="mappingDirectoryLocations">
            <list>
                <value>classpath:me/gacl/model/hbm</value>
            </list>
        </property>
         -->
    </bean>

    <!-- 配置事务管理器 -->
    <bean name="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

    <!-- 注解方式配置事物 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

#BaseDao.Java

public interface BaseDaoInter<K extends Serializable ,T extends Serializable> {
    /**
     * 由session工厂获取当前session对象
     * @return
     */
    public Session getSession();
    /**
     * 将实体对象保存到数据库中
     * @param t 待保存的实体对象
     * @return 实体对象的ID
     */
    public K save(T t);
    /**
     * 将实体对象【集合】保存到数据库中
     * @param ct 实体对象【集合】
     */
    public void saveAll(Collection<T> 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<T> ct);
    /**
     * 根据id删除一条记录
     * @param id 待删除记录id
     * @return 是否删除成功(id是否有效)
     */
    public boolean deleteById(K id);
    /**
     * 加载所有记录集合
     * @return 所有记录集合
     */
    public QueryResult<T> loadAll();
    /**
     * 分页加载记录集合
     * @param page 当前第多少页
     * @param rows 每页最多多少行数据
     * @return 第page页的数据集合
     */
    public QueryResult<T> load(int page,int rows);
    /**
     * 获取总记录数
     * @return 总数
     */
    public long getTotalCount();

    /******************************HQL******************************/
    /**
     * 分页获取所有记录
     * @return
     */
    public QueryResult<T> getScrollData();
    /**
     * 分页获取记录
     * @param firstResult 开始索引,如果输入值为-1,即获取全部数据
     * @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
     * @return
     */
    public QueryResult<T> getScrollData(int firstResult, int maxResult);
    /**
     * 分页获取记录
     * @param firstResult 开始索引,如果输入值为-1,即获取全部数据
     * @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
     * @param orderby 排序,Key为排序属性,Value为asc/desc,如:
     *  LinkedHashMap<String, String> orderby = new LinkedHashMap<String, String>();
        orderby.put("email", "asc");
        orderby.put("password", "desc");
     * @return
     */
    public QueryResult<T> getScrollData(int firstResult, int maxResult, LinkedHashMap<String, String> orderby);
    /**
     * 分页获取记录
     * @param firstResult 开始索引,如果输入值为-1,即获取全部数据
     * @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
     * @param where 条件语句,不带where关键字,条件语句只能使用位置参数,位置参数的索引值以1开始,如:o.username=?1 and o.password=?2
     * @param params 条件语句出现的位置参数值
     * @return
     */
    public QueryResult<T> 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<String, String> orderby = new LinkedHashMap<String, String>();
        orderby.put("email", "asc");
        orderby.put("password", "desc");
     * @return
     */
    public QueryResult<T> getScrollData(int firstResult, int maxResult, String where, Object[] params, LinkedHashMap<String, String> orderby);

}

#CarDao.java

public interface CarDaoInter extends BaseDaoInter<Integer,Car>{
	//定义扩展的方法
}

#DriverDao.java

public interface DriverDaoInter extends BaseDaoInter<Integer,Driver>{
       //定义扩展的方法

}

#PassengerDao.java

public interface PassengerDaoInter extends BaseDaoInter<Integer,Passenger>{
      //定义扩展的方法	

}

#BaseDaoImpl.java

/**
 * 不一定必须是abstract类型的, 请不要对BaseDaoImpl使用@Repository注解,因为无法直接指定clatt属性值
 * class值由继承类来指定
 *
 * @author BearSmall
 *
 * @param <T>
 */
public abstract class BaseDaoImpl<K extends Serializable, T extends Serializable>
		implements BaseDaoInter<K, T> {
	@Autowired
	private SessionFactory sessionFactory; // 从容器中注入session工厂【无需get,set方法】

	private Class<T> clatt; // 【实体类对应的Class对象】

	/**
	 * //向子类暴露的接口获用来获取sessionFactory
	 *
	 * @return sessionFactory
	 */
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	/**
	 * 保留指定clatt值的接口【通过子类显示调用父类的构造函数来指定】
	 *
	 * @param clatt
	 */
	public BaseDaoImpl(Class<T> clatt) {
		this.clatt = clatt;
	}

	// @SuppressWarnings("unchecked")
	// public BaseDaoImpl() {//另外一种方式指定clatt值,要求类必须是abstract类型
	// ParameterizedType parameterizedType =
	// (ParameterizedType)this.getClass().getGenericSuperclass();
	// clatt= (Class<T>)(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<T> 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<T> 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<T> loadAll() {
		Session session = getSession();
		Criteria criteria = session.createCriteria(clatt);
		QueryResult<T> result = new QueryResult<>();
		result.setDatas(criteria.list());
		result.setTotalCount(Long.parseLong(criteria
				.setProjection(Projections.rowCount()).uniqueResult()
				.toString()));
		return result;
	}

	@SuppressWarnings("unchecked")
	@Override
	public QueryResult<T> load(int page, int rows) {
		Session session = getSession();
		Criteria criteria = session.createCriteria(clatt);
		criteria.setFirstResult((page - 1) * rows);
		criteria.setMaxResults(rows);
		QueryResult<T> 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<T> getScrollData() {
		return getScrollData(-1, -1, null, null, null);
	}

	@Override
	public QueryResult<T> getScrollData(int firstResult, int maxResult) {
		return getScrollData(firstResult, maxResult, null, null, null);
	}

	@Override
	public QueryResult<T> getScrollData(int firstResult, int maxResult,
			LinkedHashMap<String, String> orderby) {
		return getScrollData(firstResult, maxResult, null, null, orderby);
	}

	@Override
	public QueryResult<T> getScrollData(int firstResult, int maxResult,
			String where, Object[] params) {
		return getScrollData(firstResult, maxResult, where, params, null);
	}

	@Override
	@SuppressWarnings("unchecked")
	public QueryResult<T> getScrollData(int firstResult, int maxResult,
			String where, Object[] params, LinkedHashMap<String, String> 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<T> qr = new QueryResult<T>();
		// 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<String, String> orderby) {
		StringBuilder sb = new StringBuilder();
		if (orderby != null && !orderby.isEmpty()) {
			sb.append(" order by ");
			for (Map.Entry<String, String> entry : orderby.entrySet()) {
				sb.append("o.").append(entry.getKey()).append(" ")
						.append(entry.getValue()).append(‘,‘);
			}
			sb.deleteCharAt(sb.length() - 1);
		}
		return sb.toString();
	}

}

#CarDaoImpl.java

@Repository("carDao")
public class CarDaoImpl extends BaseDaoImpl<Integer,Car> implements CarDaoInter{
	//通过调用父类的构造函数指定clazz值,即实体类的类类型
	public CarDaoImpl() {
		super(Car.class);
	}
     /*****************************************扩展的方法的实现****************************************/

}

#DriverDaoImpl.java

@Repository(value="driverDao")
public class DriverDaoImpl extends BaseDaoImpl<Integer,Driver> implements DriverDaoInter{
	//通过调用父类的构造函数指定clazz值,即实体类的类类型
	public DriverDaoImpl() {
		super(Driver.class);
	}

    /*****************************************扩展的方法的实现****************************************/	

}

#PassengerDaoImpl.java

@Repository("passengerDao")
public class PassengerDaoImpl extends BaseDaoImpl<Integer,Passenger> implements PassengerDaoInter {
	//通过调用父类的构造函数指定clazz值,即实体类的类类型
	public PassengerDaoImpl() {
		super(Passenger.class);
	}
       /*****************************************扩展的方法的实现****************************************/		

}

#BaseService.java

public interface BaseServiceInter<K extends Serializable,T extends Serializable>  {
	/**
	 * 将实体对象保存到数据库中
	 * @param t 待保存的实体对象
	 * @return 实体对象的ID
	 */
	public K save(T t);
	/**
	 * 将实体对象【集合】保存到数据库中
	 * @param ct 实体对象【集合】
	 */
	public void saveAll(Collection<T> 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<T> ct);
	/**
	 * 根据id删除一条记录
	 * @param id 待删除记录id
	 * @return 是否删除成功(id是否有效)
	 */
	public boolean deleteById(K id);
	/**
	 * 加载所有记录集合
	 * @return 所有记录集合
	 */
	public QueryResult<T> loadAll();
	/**
	 * 分页加载记录集合
	 * @param page 当前第多少页
	 * @param rows 每页最多多少行数据
	 * @return 第page页的数据集合
	 */
	public QueryResult<T> load(int page,int rows);
	/**
	 * 获取总记录数
	 * @return 总数
	 */
	public long getTotalCount();
	/******************************HQL******************************/
	/**
	 * 分页获取所有记录
	 * @return
	 */
	public QueryResult<T> getScrollData();
	/**
	 * 分页获取记录
	 * @param firstResult 开始索引,如果输入值为-1,即获取全部数据
	 * @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
	 * @return
	 */
	public QueryResult<T> getScrollData(int firstResult, int maxResult);
	/**
	 * 分页获取记录
	 * @param firstResult 开始索引,如果输入值为-1,即获取全部数据
	 * @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
	 * @param orderby 排序,Key为排序属性,Value为asc/desc,如:
	 *  LinkedHashMap<String, String> orderby = new LinkedHashMap<String, String>();
		orderby.put("email", "asc");
		orderby.put("password", "desc");
	 * @return
	 */
	public QueryResult<T> getScrollData(int firstResult, int maxResult, LinkedHashMap<String, String> orderby);
	/**
	 * 分页获取记录
	 * @param firstResult 开始索引,如果输入值为-1,即获取全部数据
	 * @param maxResult 每页获取的记录数,如果输入值为-1,即获取全部数据
	 * @param where 条件语句,不带where关键字,条件语句只能使用位置参数,位置参数的索引值以1开始,如:o.username=?1 and o.password=?2
	 * @param params 条件语句出现的位置参数值
	 * @return
	 */
	public QueryResult<T> 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<String, String> orderby = new LinkedHashMap<String, String>();
		orderby.put("email", "asc");
		orderby.put("password", "desc");
	 * @return
	 */
	public QueryResult<T> getScrollData(int firstResult, int maxResult, String where, Object[] params, LinkedHashMap<String, String> orderby);

}

#CarService.java

public interface CarServiceInter extends BaseServiceInter<Integer,Car>{
	//定义扩展的方法
}

#DriverService.java

public interface DriverServiceInter extends BaseServiceInter<Integer,Driver>{
	//定义扩展的方法
}

#PassengerService.java

public interface PassengerServiceInter extends BaseServiceInter<Integer,Passenger>{
	//定义扩展的方法
}

#BaseServiceImpl.java

@Transactional(propagation=Propagation.REQUIRED)
public abstract class BaseServiceImpl<K extends Serializable,T extends Serializable> implements BaseServiceInter<K,T> {

	@Autowired
	private BaseDaoInter<K,T> baseDao;		//从容器中注入session工厂【无需get,set方法】

	@Override
	public K save(T t) {
		return baseDao.save(t);
	}

	@Override
	public void saveAll(Collection<T> 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<T> ct) {
		baseDao.deleteAll(ct);
	}

	@Override
	public boolean deleteById(K id) {
		return baseDao.deleteById(id);
	}

	@Override
	public QueryResult<T> loadAll() {
		return baseDao.loadAll();
	}

	@Override
	public QueryResult<T> load(int page, int rows) {
		return baseDao.load(page, rows);
	}

	@Override
	public long getTotalCount() {
		return baseDao.getTotalCount();
	}
	/******************************HQL******************************/

	@Override
	public QueryResult<T> getScrollData() {
		return baseDao.getScrollData();
	}

	@Override
	public QueryResult<T> getScrollData(int firstResult, int maxResult) {
		return baseDao.getScrollData(firstResult, maxResult);
	}

	@Override
	public QueryResult<T> getScrollData(int firstResult, int maxResult,
			LinkedHashMap<String, String> orderby) {
		return baseDao.getScrollData(firstResult, maxResult, orderby);
	}

	@Override
	public QueryResult<T> getScrollData(int firstResult, int maxResult,
			String where, Object[] params) {
		return baseDao.getScrollData(firstResult, maxResult, where, params);
	}

	@Override
	public QueryResult<T> getScrollData(int firstResult, int maxResult,
			String where, Object[] params, LinkedHashMap<String, String> orderby) {
		return baseDao.getScrollData(firstResult, maxResult, where, params, orderby);
	}

}

#CarServiceImpl.java

@Service("carProxy")
public class CarServiceImpl extends BaseServiceImpl<Integer,Car> implements CarServiceInter {
    @Autowired
    private CarDaoInter carDao;        //从容器中注入session工厂【无需get,set方法】

      /*****************************************扩展的方法的实现****************************************/	

 }

#DriverServiceImpl.java

@Service("driverProxy")
public class DriverServiceImpl extends BaseServiceImpl<Integer,Driver> implements DriverServiceInter {
	@Autowired
	private DriverDaoInter driverDao;		//从容器中注入session工厂【无需get,set方法】 

       /*****************************************扩展的方法的实现****************************************/	

}

#PassengerServiceImpl.java

@Service("passengerProxy")
public class PassengerServiceImpl extends BaseServiceImpl<Integer,Passenger> implements PassengerServiceInter {
	@Autowired
	private PassengerDaoInter passengerDao;		//从容器中注入session工厂【无需get,set方法】 

      /*****************************************扩展的方法的实现****************************************/	

}

Plus:源代码传送门:https://github.com/bearsmall/BASESSH2

原文地址:http://blog.csdn.net/u014424628/article/details/51560256

时间: 2024-10-06 08:47:46

基于Spring4+Hibernate4的通用数据访问层+业务逻辑层(Dao层+Service层)设计与实现!的相关文章

基于Spring4+Hibernate4的通用数据访问层(Dao层)设计与实现!

基于泛型的依赖注入.当我们的项目中有很多的Model时,相应的Dao(DaoImpl),Service(ServiceImpl)也会增多. 而我们对这些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.getTotal

在 ASP.NET 中创建数据访问和业务逻辑层(转)

.NET Framework 4 当在 ASP.NET 中处理数据时,可从使用通用软件模式中受益.其中一种模式是将数据访问代码与控制数据访问或提供其他业务规则的业务逻辑代码分开.在此模式中,这两个层均与表示层分离.表示层由网站用户有权查看或更改数据的页面组成. ASP.NET 可通过多种方式提供数据访问.业务逻辑和表示形式之间的分离.例如,数据源模型(包括 LinqDataSource 和 ObjectDataSource 等服务器控件)可将表示层与数据访问代码和业务逻辑分离. 另一种模式是将数

Java通用数据访问层Fastser-DAL推荐

本着不重复造轮子的原则,基于mybatis.spring jdbc.hibernate等ORM的通用数据访问层,支持基于datasource的读写分离.主备自动切换和故障转移,支持简单的负载均衡. 源码地址:http://git.oschina.net/fastser/fastser-dal-all 特性: 基于mybatis.spring jdbc.hibernate等各大orm框架实现通用dal层功能,并可以与已有项目完全兼容.同时也可以在已经实现的orm框架之间任意切换,不需要对代码作任何

ssh通用数据访问层接口及实现

package org.dao; import java.io.Serializable;import java.util.LinkedHashMap;import java.util.List;import java.util.Map; /** * 通用数据访问层 */ public interface BaseDao<T> { /** * 保存单个实体 * @param entity */ public void save(T entity); /** * 级联保存单个实体对象 * @pa

为何有DAO与Service层?为何先搞Dao接口在搞DaoImpl实现?直接用不行吗?

转自 http://blog.sina.com.cn/s/blog_4b1452dd0102wvox.html 我们都知道有了Hibernate后,单独对数据的POJO封装以及XML文件要耗损掉一个类(Orz意思是你需要精力写一个类).然后,在大部分的服务中,我们又需要单独写一个Dao接口,并加个DaoImpl实现来操作数据库(好吧,再耗损2个类).紧接着,我们发现其实Service层也要单独写一个类(再加1个). 一共4个类外加1个xml--这不是作死么,5个文件.人家好端端地写PHP可能在一

ADO.NET笔记——使用通用数据访问

相关知识: 前面所有示例,君是访问特定的数据库(SQL Server),因此注入SqlConnection.SqlCommand.SqlDataReader.SqlDataAdapter等类名都添加了“Sql”的前缀,并且隶属于System.Data.SqlClient命名空间.这就给代码的可移植性带来了巨大问题.如果数据库改用Oracle.MySQL或者BD2,代码几乎要全部重写,非常不利于重用. System.Data.Common命名空间提供了一组类和操作,使得程序可以忽略底层数据库的差异

基于SpringMVC+Spring+MyBatis实现秒杀系统【业务逻辑】

前言 该篇主要实现秒杀业务层,秒杀业务逻辑里主要包括暴露秒杀接口地址.实现秒杀业务逻辑.同时声明了三个业务类:Exposer.SeckillExecution.SeckillResult. Exposer主要用来实现暴露接口时一个md5的加密,防止用户在客户端篡改数据.根据seckillid生成md5,提交秒杀请求时会根据这个md5和seckillid比对是否是合法的请求.SeckillExecution主要封装秒杀时的返回值. SeckillExecution有2个属性,state.state

从零开始,搭建博客系统MVC5+EF6搭建框架(1),EF Code frist、实现泛型数据仓储以及业务逻辑

前言      从上篇30岁找份程序员的工作(伪程序员的独白),文章开始,我说过我要用我自学的技术,来搭建一个博客系统,也希望大家给点意见,另外我很感谢博客园的各位朋友们,对我那篇算是自我阶段总结文章的评论,在里面能看出有很多种声音,有支持的我的朋友给我加油打气,有分享自己工作经历的朋友,有提出忠肯意见的朋友,有对记事本写代码吐槽的朋友,也有希望让我换个行业的,觉得我可能不适合这个行业朋友,不管怎样,我都接受,都是大家同行的一些忠告,谢谢大家. 首先我要在这里感谢很多博客园里面的大牛,写了很多系

面对数据丢失、数据错误、业务逻辑发生变化时,可以这么解决。

根据福克斯新闻在20日的报道,美国田纳西州一名14岁男孩Jackson成功在家中打造出核融合实验的小型聚变反应器,成功结合2个氘原子.释出一颗中子. 关键是,Jackson所需的零件是从网上购买,或自己改装的.而且仅用一年时间就打造出了反应器.美媒称,他可能打破了全球最年轻核科学家Taylor Wilson的纪录,是年纪最小的完成制作了核聚变反应器的"科学家". 嗯,还是别人家的孩子,惹不起惹不起!然而没有对比就没有伤害,说出来不怕你们笑话我(们): 面对数据丢失的我 我在公司负责统计