`
周一Monday
  • 浏览: 342286 次
  • 来自: 北京
社区版块
存档分类
最新评论

基于Spring、Hibernate的通用DAO层与Service层的实现

 
阅读更多

因为DAO层基本的就是CRUD操作,变化不是很大,要是有变化的那就是查询。而确实没有必要为每一个实体写一个完整的DAO,但是没有还不行,那就“抽取”出来吧。而Service依赖与DAO层,有时就是简单调用一下,也确实没有必要每个都写。总之,不爱写多个,那就写一个通用的,而其他的继承或实现这个通用的可以了。

还是用代码说话吧。

package org.monday.dao;

import java.io.Serializable;
import java.util.List;

/**
 * BaseDAO 定义DAO的通用操作
 * 
 * @author Monday
 */
public interface BaseDao<T> {

	public void save(T entity);

	public void update(T entity);

	public void delete(Serializable id);

	public T findById(Serializable id);

	public List<T> findByHQL(String hql, Object... params);

}

 

 

上面的DAO只定义了一些常见的方法,有需要通用的方法,可以随便加,然后实现它就行了。 

package org.monday.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.monday.dao.BaseDao;

/**
 * BaseDaoImpl 定义DAO的通用操作的实现
 * 
 * @author Monday
 */
@SuppressWarnings("unchecked")
public class BaseDaoImpl<T> implements BaseDao<T> {

	private Class<T> clazz;

	/**
	 * 通过构造方法指定DAO的具体实现类
	 */
	public BaseDaoImpl() {
		ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
		clazz = (Class<T>) type.getActualTypeArguments()[0];
		System.out.println("DAO的真实实现类是:" + this.clazz.getName());
	}

	/**
	 * 向DAO层注入SessionFactory
	 */
	@Resource
	private SessionFactory sessionFactory;

	/**
	 * 获取当前工作的Session
	 */
	protected Session getSession() {
		return this.sessionFactory.getCurrentSession();
	}

	public void save(T entity) {
		this.getSession().save(entity);
	}

	public void update(T entity) {
		this.getSession().update(entity);
	}

	public void delete(Serializable id) {
		this.getSession().delete(this.findById(id));
	}

	public T findById(Serializable id) {
		return (T) this.getSession().get(this.clazz, id);
	}

	public List<T> findByHQL(String hql, Object... params) {
		Query query = this.getSession().createQuery(hql);
		for (int i = 0; params != null && i < params.length; i++) {
			query.setParameter(i, params);
		}
		return query.list();
	}
}

 

 

 

以上是BaseDao和它的实现类。

那下面以CustomerDao与OrderDao为例,编写具体的Dao

 

 

package org.monday.dao;

import org.monday.domain.Customer;

/**
 * 客户DAO继承BaseDAO
 * 
 * @author Monday
 */
public interface CustomerDao extends BaseDao<Customer> {

	/**
	 * 若BaseDAO 没有定义的方法,可以在这里添加
	 */
}

 

package org.monday.dao.impl;

import org.monday.dao.CustomerDao;
import org.monday.domain.Customer;
import org.springframework.stereotype.Repository;

/**
 * 客户DAO的实现类 继承BaseDaoImpl 显示客户DAO接口
 * 
 * @author Monday
 */
@Repository(value = "customerDao")
public class CustomerDaoImpl extends BaseDaoImpl<Customer> implements CustomerDao {

	/**
	 * 若CustomerDao 定义了BaseDAO没有的方法,则可以在这里实现
	 */
}

 

package org.monday.dao;

import org.monday.domain.Order;

/**
 * 订单DAO继承BaseDAO
 * 
 * @author Monday
 */
public interface OrderDao extends BaseDao<Order> {
	/**
	 * 若BaseDAO 没有定义的方法,可以在这里添加
	 */
}
package org.monday.dao.impl;

import org.monday.dao.OrderDao;
import org.monday.domain.Order;
import org.springframework.stereotype.Repository;

/**
 * 订单DAO的实现类 继承BaseDaoImpl 显示订单DAO接口
 * 
 * @author Monday
 */
@Repository(value = "orderDao")
public class OrderDaoImpl extends BaseDaoImpl<Order> implements OrderDao {

	/**
	 * 若OrderDao 定义了BaseDAO没有的方法,则可以在这里实现
	 */
}

 

 

至于具体的Service怎么写呢?看下面: 

package org.monday.service;

import java.io.Serializable;
import java.util.List;

/**
 * BaseService 定义Service的通用操作
 * 
 * @author Monday
 */
public interface BaseService<T> {

	public void save(T entity);

	public void update(T entity);

	public void delete(Serializable id);

	public T getById(Serializable id);

	public List<T> getByHQL(String hql, Object... params);
}

 

package org.monday.service.impl;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.monday.dao.BaseDao;
import org.monday.service.BaseService;
import org.springframework.transaction.annotation.Transactional;


/**
 * BaseServiceImpl 定义Service的通用操作的实现
 * 
 * @author Monday
 */
@Transactional
public class BaseServiceImpl<T> implements BaseService<T> {
	
	/**
	 * 注入BaseDao
	 */
	private BaseDao<T> dao;
	@Resource
	public void setDao(BaseDao<T> dao) {
		this.dao = dao;
	}

	public void save(T entity) {
		dao.save(entity);
	}

	public void update(T entity) {
		dao.update(entity);
	}

	public void delete(Serializable id) {
		dao.delete(id);
	}

	public T getById(Serializable id) {
		return dao.findById(id);
	}

	public List<T> getByHQL(String hql, Object... params) {
		return dao.findByHQL(hql, params);
	}
}

 

package org.monday.service;

import org.monday.domain.Customer;

/**
 * 客户Service继承BaseService
 * 
 * @author Monday
 */
public interface CustomerService extends BaseService<Customer> {
	/**
	 * 若BaseService 没有定义的方法,可以在这里添加
	 */
}
package org.monday.service.impl;

import javax.annotation.Resource;

import org.monday.dao.BaseDao;
import org.monday.domain.Customer;
import org.monday.service.CustomerService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 客户Service的实现类 继承BaseServiceImpl 显示客户Service接口
 * 
 * @author Monday
 */

@Service("customerService")
@Transactional
public class CustomerServiceImpl extends BaseServiceImpl<Customer> implements CustomerService {

	/**
	 * 注入DAO
	 */
	@Resource(name = "customerDao")
	public void setDao(BaseDao<Customer> dao) {
		super.setDao(dao);
	}

	/**
	 * 若CustomerService 定义了BaseService没有的方法,则可以在这里实现
	 */

}

 

package org.monday.service;

import org.monday.domain.Order;

/**
 * 订单Service继承BaseService
 * 
 * @author Monday
 */
public interface OrderService extends BaseService<Order> {
	/**
	 * 若BaseService 没有定义的方法,可以在这里添加
	 */
}

 

package org.monday.service.impl;

import javax.annotation.Resource;

import org.monday.dao.BaseDao;
import org.monday.domain.Order;
import org.monday.service.OrderService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 订单Service的实现类 继承BaseServiceImpl 显示订单Service接口
 * 
 * @author Monday
 */

@Service(value = "orderService")
@Transactional
public class OrderServiceImpl extends BaseServiceImpl<Order> implements OrderService {

	/**
	 * 注入DAO
	 */
	@Resource(name = "orderDao")
	public void setDao(BaseDao<Order> dao) {
		super.setDao(dao);
	}

	/**
	 * 若CustomerService 定义了BaseService没有的方法,则可以在这里实现
	 */
}

  

这里只是提供了一个思路。可能代码还有不严谨的地方,欢迎补充指正。

容易出现的两个异常:

1.org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

 

答案:要加@Transactional注解

除了要在这里加注解

@Service("customerService")
@Transactional

public class CustomerServiceImpl extends BaseServiceImpl<Customer> implements CustomerService {}

 

这里也要加

@Transactional

public class BaseServiceImpl<T> implements BaseService<T> {}

 

2.org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerService':
Injection of resource fields failed;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [org.monday.dao.BaseDao] is defined:
expected single matching bean but found 2: [customerDao, orderDao]

 

答案:

(参考)

注入具体的DAO

@Resource(name="customerDao")
 public void setDao(BaseDao<Customer> dao) {
  super.setDao(dao);
 }

 

PS:画个图好了。

 

 

 

分享到:
评论
7 楼 chen_juns 2015-12-11  
虽然通过接口方式省了一些代码,但每一个实体还是要写一个DAO,不觉得这样很麻烦吗
6 楼 sunxiaoyes 2014-12-27  
sunxiaoyes 写道
拿不到clazz怎么破

我是用的楼主的通用dao,但是拿不到泛型实际类型
5 楼 sunxiaoyes 2014-12-27  
拿不到clazz怎么破
4 楼 junlintianxia1234 2014-06-29  
spring配置文件是怎样配置的,能提供一下吗?按照你的方式,我的程序报错为
org.hibernate.HibernateException: No CurrentSessionContext configured!
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1039)
at topsun.rms.dao.BaseDao.getSession(BaseDao.java:48)
at topsun.rms.dao.BaseDao.findByHQL(BaseDao.java:73)
at topsun.rms.services.BaseService.getByHQL(BaseService.java:52)
at topsun.rms.web.CustomUserController.getAllUser(CustomUserController.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:746)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:687)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:822)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)
3 楼 山扬L 2013-08-09  
findByHQL(String hql, Object... params)

query.setParameter(i, params); 
是不是的改成
query.setParameter(i, params[i]);  ?????
2 楼 学海无涯穷欢乐 2013-05-10  
ws347575294 写道
@Service(value = "orderService") 
@Transactional 
public class OrderServiceImpl extends BaseServiceImpl<Order> implements OrderService { 
 
    /**
     * 注入DAO
     */ 
    @Resource(name = "orderDao") 
    public void setDao(BaseDao<Order> dao) { 
        super.setDao(dao); 
    } 
 
    /**
     * 若CustomerService 定义了BaseService没有的方法,则可以在这里实现
     */ 
如果在这里注入了多个DAO会出错,它总是记录着最后一个被注入的DAO .

求解决 ?



ws347575294 写道
@Service(value = "orderService") 
@Transactional 
public class OrderServiceImpl extends BaseServiceImpl<Order> implements OrderService { 
 
    /**
     * 注入DAO
     */ 
    @Resource(name = "orderDao") 
    public void setDao(BaseDao<Order> dao) { 
        super.setDao(dao); 
    } 
 
    /**
     * 若CustomerService 定义了BaseService没有的方法,则可以在这里实现
     */ 
如果在这里注入了多个DAO会出错,它总是记录着最后一个被注入的DAO .

求解决 ?


如果想实现注入多个Dao  解决方法是
@Service(value = "orderService") 
@Transactional 
public class OrderServiceImpl extends BaseServiceImpl<Order> implements OrderService { 
 
    /**
     * 注入DAO
     */ 
    @Resource(name = "orderDao") 
    public void setDao(BaseDao<Order> dao) { 
        super.setDao(dao); 
    } 
 
    /**
     * 若CustomerService 定义了BaseService没有的方法,则可以在这里实现
     */ 


去掉 extends BaseServiceImpl<Order> 即可。原因是,继承过来   /**
     * 注入BaseDao
     */ 
    private BaseDao<T> dao; 
    @Resource 
    public void setDao(BaseDao<T> dao) { 
        this.dao = dao; 
    } 
  中的dao。    @Resource   没有注入任何dao。所以会搜索所有的Dao进行注入,因此导致异常No unique bean of type 。
上面的方法可以解决多daozhuru

2.没有验证过,只是提供解决思路:
如果非要extends BaseServiceImpl<Order> ,  解决方法, * 注入BaseDao
     */ 
    private BaseDao<T> dao; 
    @Resource 
    public void setDao(BaseDao<T> dao) { 
        this.dao = dao; 
    }  中@Resource 必须注入一个T类型的Dao动态的进行注入。应该利用反射等知识。

反正这种假设不太对。

如果非得继承extends BaseServiceImpl<Order>   那最好去掉private BaseDao<T> dao; 
    @Resource 
    public void setDao(BaseDao<T> dao) { 
        this.dao = dao; 
    }

然后在自己的子类中进行注入
@Resource(name="customerDao")
private BaseDao<Customer> customerDao;
@Resource(name="orderDao")
private  BaseDao<Order> orderDao;
 
1 楼 ws347575294 2012-04-04  
@Service(value = "orderService") 
@Transactional 
public class OrderServiceImpl extends BaseServiceImpl<Order> implements OrderService { 
 
    /**
     * 注入DAO
     */ 
    @Resource(name = "orderDao") 
    public void setDao(BaseDao<Order> dao) { 
        super.setDao(dao); 
    } 
 
    /**
     * 若CustomerService 定义了BaseService没有的方法,则可以在这里实现
     */ 
如果在这里注入了多个DAO会出错,它总是记录着最后一个被注入的DAO .

求解决 ?

相关推荐

    一个通用的dao和service包

    向你的service里注入dao(spring配置文件),dao是这个包里的类 &lt;bean id="employeeService" class="com.erp.service.impl.EmployeeServiceImpl"&gt; &lt;bean class="com.xvxv.common.dao.impl.EntityDaoImpl"&gt; ...

    虚拟数据层 Struts2、Hibernate、Spring整合的泛型DAO Version 2010.9.27

    Struts2、Hibernate、Spring整合的泛型DAO (本人评价: 代码开发效率提高30% 代码出错率减少70%) 对于大多数开发人员,系统中的每个 DAO 编写几乎相同的代码到目前为止已经成为一种习惯。虽然所有人都将这种重复...

    spring+springmvc+hibernate框架配置源码

    该demo集成了spring+springmvc+hibernate框架,里面的dao、service、entity均采用注解形式,容易开发,另外该demo中dao采用注解形式,将所有实体dao需要用到的通用方法如insert,update,delete,分页查询等均采用...

    Maven Struts-Spring-Hibernate全注解示例

    一、部分软件/库版本 Maven:3.0.5 struts2.2.3-spring3.0.6-hibernate3.6.6 二、Demo功能(导入sql可直接运行) 1.数据库文件doc/db.sql ... 实现了对任何通用CRUD(增删改查)操作,不用写任何Service/Dao层代码

    泛型dao 泛型dao 泛型dao

    Struts2、Hibernate、Spring整合的泛型DAO (本人评价: 代码开发效率提高30% 代码出错率减少70%) 对于大多数开发人员,系统中的每个 DAO 编写几乎相同的代码到目前为止已经成为一种习惯。虽然所有人都将这种重复...

    Spring.3.x企业应用开发实战(完整版).part2

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    Spring3.x企业应用开发实战(完整版) part1

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    Spring中文帮助文档

    12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...

    Spring API

    12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    由于J2EE的开源的框架中提供了MVC模式实现框架Struts、对象关系模型中的Hibernate 的框架及拥有事务管理和依赖注入的Spring。利用现存框架可以更快开发系统。所以选择Java技术作为blog 的开发工具。 为了增加系统的...

    springmvc4_hibernate4.3_JPA2.1_Shiro1.2_Ehcache

    spring4.04,springmvc, hibernate4.3 ,JPA2.1, shiro1.2, ehcache2 完全整合,用Ehcache做缓存,通用的DAO、Service接口和实现。完全注解配置,事务拦截方式处理。C0p3做连接池,JSP和Freemarker做View的模板。Shiro...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    该案例采用目前最流行、最规范的java ee架构,整个应用分为jpa实体层、eao层、业务逻辑层、mvc层和视图层,各层之间分层清晰,层与层之间以松耦合的方法组织在一起。该案例既提供了ide无关的、基于ant管理的项目源码...

    SSH代码生成器(通用)

    全自动生成Struts2 Hibernate3.6 Spring2.5 自动生成DAO,Service,Action,以及配置文件; 运行CreateSrc.java文件, 修改main()中的方法, 自定义要生成对象的名称; 运行后,请刷新工程可看到生成的文件

    java面试题

    4:Spring DAO:打开关闭数据库连接 5:Spring WEB:为基于WEB服务的应用程序提供上下文服务 6:Spring Context:向Spring框架提供上下文信息 7:Spring MVC:分离模型、视图、控制器、以便更容易定制 折构函数...

    积分管理系统java源码-mystyle:我的风格

    使用泛型封装dao、service、controller基类,包含分页,查询条件封装,从而达到快速crud操作 基于hibernate简单查询条件的封装 权限管理——使用框架apache shiro进行系统认证、授权操作(完成) 系统认证、授权操作 ...

    cms后台管理

    Jeecms是基于Spring注解,在自定义标签时对于实体类和dao service等注意注解的问题。 五 自定义标签及使用自己创建的表的实现过程 下面是我自己定义的标签mycontent_list 首先,在数据库里创建了一个jc_...

Global site tag (gtag.js) - Google Analytics