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

基于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 .

求解决 ?

相关推荐

    Struts2+hibernate+spring整合泛型DAO

    整合Struts2、Hibernate和Spring,我们通常会使用Spring的ApplicationContext来管理Bean,包括Action类、Service层和DAO层。Service层作为业务逻辑层,调用DAO层的方法进行数据操作。而DAO层通过泛型接口和实现类,...

    Struts2 Spring3 Hibernate 注解功能 DAO 泛型 通用分页

    总的来说,"SSHWithAnnotationDemo"项目展示了如何利用现代Java技术栈的高级特性,包括Struts2、Spring3和Hibernate的注解功能,DAO层的泛型设计以及通用的分页实现,来构建一个高效、可维护的Web应用。这样的实践...

    基于Annotation并对DAO层封装具有分页功能的S2SH整合实例

    在Java Web开发中,S2SH(Struts2 + Spring + Hibernate)是一个常见的技术栈,它结合了MVC框架Struts2、依赖注入容器Spring以及持久层框架Hibernate,以实现高效且灵活的Web应用开发。在这个基于Annotation并对DAO...

    基于struts2 spring hibernate 开发的bbs论坛

    本项目"基于Struts2 Spring Hibernate开发的BBS论坛"是一个典型的MVC(Model-View-Controller)架构的实例,旨在帮助初学者理解并掌握这些技术的实际应用。 Struts2作为MVC框架,主要负责控制层,它的主要任务是...

    基于注解整合spring与hibernate

    本文将深入探讨如何基于注解的方式整合Spring与Hibernate,帮助新手更好地理解和实践这两个框架的整合。 首先,让我们了解Spring中的注解。Spring注解如`@Autowired`、`@Service`、`@Repository`和`@Controller`...

    hibernate 通用接口架构

    "hibernate 通用接口架构"是指利用Hibernate框架,通过设计DAO(Data Access Object)层的接口来实现业务逻辑与数据访问的解耦,从而提高代码的可复用性和可维护性。 首先,我们来理解DAO层的作用。DAO层作为业务...

    Spring+Hibernate实现)Hibernate公用类

    本文将详细解析如何利用Spring和Hibernate来实现一个通用的DAO(Data Access Object)层,以提高代码复用性和项目开发效率。 首先,让我们了解Spring框架。Spring是一个全面的企业级应用开发框架,提供了依赖注入...

    使用maven整合spring和hibernate的例子(spring mvc)

    同时,还需要配置Hibernate的实体类、DAO层接口及其实现、Service层接口及其实现、以及Controller层。 接着,创建Hibernate的实体类,通过注解(如@Entity、@Table、@Id、@GeneratedValue等)定义与数据库表的映射...

    Spring的作用贯穿了整个中间层,将Web层、Service层、DAO层及PO无缝整合,其数据服务层用来存放数据。

    具体来说,Spring可以将Web层、Service层、DAO层以及PO(Plain Old Java Object)对象无缝整合在一起,形成一个完整而高效的应用程序架构。 - **Web层**:处理与用户交互相关的部分,如HTTP请求的接收、处理以及...

    struts+spring+hibernate通用分页方法

    在文档"struts+spring+hibernate通用分页方法.doc"中,可能会详细阐述如何配置这些框架的整合,如何编写Action、Service、DAO以及视图层的代码,以及如何测试和优化分页性能,例如缓存策略、预加载等。 这个通用...

    Spring3.2.5Hibernate4.0.1Integration 完整範例

    在实际项目中,Spring 通常用于管理 Hibernate 的 SessionFactory,提供事务管理,并通过 AOP 实现数据访问层的通用方法,如开启和提交事务、处理异常等。 从文件名称 "Spring3.2.5Hibernate4.0.1Integration" 来看...

    maven(springmvc+spring+hibernate)

    6. **DAO和Service层**:实现数据访问对象(DAO)接口和业务服务(Service)接口,处理数据库操作和业务逻辑。 7. **Action和视图**:编写Struts Action类,实现用户请求的处理逻辑,返回相应的视图结果。 8. **测试...

    spring hibernate整合的底层数据操作方法

    总结,Spring与Hibernate的整合极大地提高了开发效率,通过Spring的IoC和AOP特性,我们可以轻松地管理数据访问层,实现通用的增删改查方法。同时,Spring Data的加入让查询更加简洁,降低了对SQL的依赖。在实际项目...

    HibernateDAO的写法

    而HibernateDAO则是基于Hibernate进行数据访问的对象,是业务逻辑层和持久层之间的桥梁。本文将详细探讨HibernateDAO的实现方式以及常见设计模式,旨在帮助开发者更好地理解和运用这一技术。 1. HibernateDAO的基本...

    Hibernate+Struts+Spring 实现的通用分页查询

    总结来说,使用Hibernate、Struts和Spring实现的通用分页查询,涉及了Java Web开发中的多个层次,包括模型、持久层接口、持久层实现、业务层和服务层的交互,以及视图层的渲染。这种分页机制灵活且可复用,可以适应...

    spring+hibernate+struts2整合

    在本项目中,Spring被用来管理数据库的SessionFactory,以及控制业务逻辑层(Service)与数据访问层(DAO)之间的交互。 **Hibernate框架**:Hibernate是一个优秀的ORM(Object-Relational Mapping)框架,它简化了...

    structs2+spring+hibernate整合

    5. **整合Hibernate和Spring**:在Spring的配置文件中声明SessionFactory Bean,并将它注入到Service层,Service层再注入到DAO层。这样,Service和DAO可以通过Spring获取SessionFactory,进行数据操作。 6. **测试**...

    基于注解ssh的通用dao的crud

    下面我们将深入探讨基于注解的SSH实现通用DAO的CRUD(创建、读取、更新、删除)操作。 首先,让我们从Spring开始。在Spring 4中,注解的使用已经非常广泛,例如`@Autowired`用于自动装配bean,`@Service`、`@...

    Spring+Hibernate完整分页

    本文将深入探讨如何利用Spring和Hibernate实现完整的分页功能,并结合MySQL数据库进行操作。 首先,Spring是一个轻量级的框架,它提供了全面的DI服务,允许开发者通过XML配置或注解来管理对象的生命周期和依赖关系...

Global site tag (gtag.js) - Google Analytics