基於Spring、Hibernate的通用DAO層與Service層的實現

因爲DAO層基本的就是CRUD操作,變化不是很大,要是有變化的那就是查詢。而確實沒有必要爲每一個實體寫一個完整的DAO,但是沒有還不行,那就“抽取”出來吧。而Service依賴與DAO層,有時就是簡單調用一下,也確實沒有必要每個都寫。總之,不愛寫多個,那就寫一個通用的,而其他的繼承或實現這個通用的可以了。

還是用代碼說話吧。

Java代碼  收藏代碼
  1. package org.monday.dao;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.List;  
  5.   
  6. /** 
  7.  * BaseDAO 定義DAO的通用操作 
  8.  *  
  9.  * @author Monday 
  10.  */  
  11. public interface BaseDao<T> {  
  12.   
  13.     public void save(T entity);  
  14.   
  15.     public void update(T entity);  
  16.   
  17.     public void delete(Serializable id);  
  18.   
  19.     public T findById(Serializable id);  
  20.   
  21.     public List<T> findByHQL(String hql, Object... params);  
  22.   
  23. }  

 

 

上面的DAO只定義了一些常見的方法,有需要通用的方法,可以隨便加,然後實現它就行了。 

Java代碼  收藏代碼
  1. package org.monday.dao.impl;  
  2.   
  3. import java.io.Serializable;  
  4. import java.lang.reflect.ParameterizedType;  
  5. import java.util.List;  
  6.   
  7. import javax.annotation.Resource;  
  8.   
  9. import org.hibernate.Query;  
  10. import org.hibernate.Session;  
  11. import org.hibernate.SessionFactory;  
  12. import org.monday.dao.BaseDao;  
  13.   
  14. /** 
  15.  * BaseDaoImpl 定義DAO的通用操作的實現 
  16.  *  
  17.  * @author Monday 
  18.  */  
  19. @SuppressWarnings("unchecked")  
  20. public class BaseDaoImpl<T> implements BaseDao<T> {  
  21.   
  22.     private Class<T> clazz;  
  23.   
  24.     /** 
  25.      * 通過構造方法指定DAO的具體實現類 
  26.      */  
  27.     public BaseDaoImpl() {  
  28.         ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();  
  29.         clazz = (Class<T>) type.getActualTypeArguments()[0];  
  30.         System.out.println("DAO的真實實現類是:" + this.clazz.getName());  
  31.     }  
  32.   
  33.     /** 
  34.      * 向DAO層注入SessionFactory 
  35.      */  
  36.     @Resource  
  37.     private SessionFactory sessionFactory;  
  38.   
  39.     /** 
  40.      * 獲取當前工作的Session 
  41.      */  
  42.     protected Session getSession() {  
  43.         return this.sessionFactory.getCurrentSession();  
  44.     }  
  45.   
  46.     public void save(T entity) {  
  47.         this.getSession().save(entity);  
  48.     }  
  49.   
  50.     public void update(T entity) {  
  51.         this.getSession().update(entity);  
  52.     }  
  53.   
  54.     public void delete(Serializable id) {  
  55.         this.getSession().delete(this.findById(id));  
  56.     }  
  57.   
  58.     public T findById(Serializable id) {  
  59.         return (T) this.getSession().get(this.clazz, id);  
  60.     }  
  61.   
  62.     public List<T> findByHQL(String hql, Object... params) {  
  63.         Query query = this.getSession().createQuery(hql);  
  64.         for (int i = 0; params != null && i < params.length; i++) {  
  65.             query.setParameter(i, params);  
  66.         }  
  67.         return query.list();  
  68.     }  
  69. }  

 

 

 

以上是BaseDao和它的實現類。

那下面以CustomerDao與OrderDao爲例,編寫具體的Dao

 

 

Java代碼  收藏代碼
  1. package org.monday.dao;  
  2.   
  3. import org.monday.domain.Customer;  
  4.   
  5. /** 
  6.  * 客戶DAO繼承BaseDAO 
  7.  *  
  8.  * @author Monday 
  9.  */  
  10. public interface CustomerDao extends BaseDao<Customer> {  
  11.   
  12.     /** 
  13.      * 若BaseDAO 沒有定義的方法,可以在這裏添加 
  14.      */  
  15. }  

 

Java代碼  收藏代碼
  1. package org.monday.dao.impl;  
  2.   
  3. import org.monday.dao.CustomerDao;  
  4. import org.monday.domain.Customer;  
  5. import org.springframework.stereotype.Repository;  
  6.   
  7. /** 
  8.  * 客戶DAO的實現類 繼承BaseDaoImpl 顯示客戶DAO接口 
  9.  *  
  10.  * @author Monday 
  11.  */  
  12. @Repository(value = "customerDao")  
  13. public class CustomerDaoImpl extends BaseDaoImpl<Customer> implements CustomerDao {  
  14.   
  15.     /** 
  16.      * 若CustomerDao 定義了BaseDAO沒有的方法,則可以在這裏實現 
  17.      */  
  18. }  

 

Java代碼  收藏代碼
  1. package org.monday.dao;  
  2.   
  3. import org.monday.domain.Order;  
  4.   
  5. /** 
  6.  * 訂單DAO繼承BaseDAO 
  7.  *  
  8.  * @author Monday 
  9.  */  
  10. public interface OrderDao extends BaseDao<Order> {  
  11.     /** 
  12.      * 若BaseDAO 沒有定義的方法,可以在這裏添加 
  13.      */  
  14. }  
Java代碼  收藏代碼
  1. package org.monday.dao.impl;  
  2.   
  3. import org.monday.dao.OrderDao;  
  4. import org.monday.domain.Order;  
  5. import org.springframework.stereotype.Repository;  
  6.   
  7. /** 
  8.  * 訂單DAO的實現類 繼承BaseDaoImpl 顯示訂單DAO接口 
  9.  *  
  10.  * @author Monday 
  11.  */  
  12. @Repository(value = "orderDao")  
  13. public class OrderDaoImpl extends BaseDaoImpl<Order> implements OrderDao {  
  14.   
  15.     /** 
  16.      * 若OrderDao 定義了BaseDAO沒有的方法,則可以在這裏實現 
  17.      */  
  18. }  

 

 

至於具體的Service怎麼寫呢?看下面: 

Java代碼  收藏代碼
  1. package org.monday.service;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.List;  
  5.   
  6. /** 
  7.  * BaseService 定義Service的通用操作 
  8.  *  
  9.  * @author Monday 
  10.  */  
  11. public interface BaseService<T> {  
  12.   
  13.     public void save(T entity);  
  14.   
  15.     public void update(T entity);  
  16.   
  17.     public void delete(Serializable id);  
  18.   
  19.     public T getById(Serializable id);  
  20.   
  21.     public List<T> getByHQL(String hql, Object... params);  
  22. }  

 

Java代碼  收藏代碼
  1. package org.monday.service.impl;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.List;  
  5.   
  6. import javax.annotation.Resource;  
  7.   
  8. import org.monday.dao.BaseDao;  
  9. import org.monday.service.BaseService;  
  10. import org.springframework.transaction.annotation.Transactional;  
  11.   
  12.   
  13. /** 
  14.  * BaseServiceImpl 定義Service的通用操作的實現 
  15.  *  
  16.  * @author Monday 
  17.  */  
  18. @Transactional  
  19. public class BaseServiceImpl<T> implements BaseService<T> {  
  20.       
  21.     /** 
  22.      * 注入BaseDao 
  23.      */  
  24.     private BaseDao<T> dao;  
  25.     @Resource  
  26.     public void setDao(BaseDao<T> dao) {  
  27.         this.dao = dao;  
  28.     }  
  29.   
  30.     public void save(T entity) {  
  31.         dao.save(entity);  
  32.     }  
  33.   
  34.     public void update(T entity) {  
  35.         dao.update(entity);  
  36.     }  
  37.   
  38.     public void delete(Serializable id) {  
  39.         dao.delete(id);  
  40.     }  
  41.   
  42.     public T getById(Serializable id) {  
  43.         return dao.findById(id);  
  44.     }  
  45.   
  46.     public List<T> getByHQL(String hql, Object... params) {  
  47.         return dao.findByHQL(hql, params);  
  48.     }  
  49. }  

 

Java代碼  收藏代碼
  1. package org.monday.service;  
  2.   
  3. import org.monday.domain.Customer;  
  4.   
  5. /** 
  6.  * 客戶Service繼承BaseService 
  7.  *  
  8.  * @author Monday 
  9.  */  
  10. public interface CustomerService extends BaseService<Customer> {  
  11.     /** 
  12.      * 若BaseService 沒有定義的方法,可以在這裏添加 
  13.      */  
  14. }  
Java代碼  收藏代碼
  1. package org.monday.service.impl;  
  2.   
  3. import javax.annotation.Resource;  
  4.   
  5. import org.monday.dao.BaseDao;  
  6. import org.monday.domain.Customer;  
  7. import org.monday.service.CustomerService;  
  8. import org.springframework.stereotype.Service;  
  9. import org.springframework.transaction.annotation.Transactional;  
  10.   
  11. /** 
  12.  * 客戶Service的實現類 繼承BaseServiceImpl 顯示客戶Service接口 
  13.  *  
  14.  * @author Monday 
  15.  */  
  16.   
  17. @Service("customerService")  
  18. @Transactional  
  19. public class CustomerServiceImpl extends BaseServiceImpl<Customer> implements CustomerService {  
  20.   
  21.     /** 
  22.      * 注入DAO 
  23.      */  
  24.     @Resource(name = "customerDao")  
  25.     public void setDao(BaseDao<Customer> dao) {  
  26.         super.setDao(dao);  
  27.     }  
  28.   
  29.     /** 
  30.      * 若CustomerService 定義了BaseService沒有的方法,則可以在這裏實現 
  31.      */  
  32.   
  33. }  

 

Java代碼  收藏代碼
  1. package org.monday.service;  
  2.   
  3. import org.monday.domain.Order;  
  4.   
  5. /** 
  6.  * 訂單Service繼承BaseService 
  7.  *  
  8.  * @author Monday 
  9.  */  
  10. public interface OrderService extends BaseService<Order> {  
  11.     /** 
  12.      * 若BaseService 沒有定義的方法,可以在這裏添加 
  13.      */  
  14. }  

 

Java代碼  收藏代碼
  1. package org.monday.service.impl;  
  2.   
  3. import javax.annotation.Resource;  
  4.   
  5. import org.monday.dao.BaseDao;  
  6. import org.monday.domain.Order;  
  7. import org.monday.service.OrderService;  
  8. import org.springframework.stereotype.Service;  
  9. import org.springframework.transaction.annotation.Transactional;  
  10.   
  11. /** 
  12.  * 訂單Service的實現類 繼承BaseServiceImpl 顯示訂單Service接口 
  13.  *  
  14.  * @author Monday 
  15.  */  
  16.   
  17. @Service(value = "orderService")  
  18. @Transactional  
  19. public class OrderServiceImpl extends BaseServiceImpl<Order> implements OrderService {  
  20.   
  21.     /** 
  22.      * 注入DAO 
  23.      */  
  24.     @Resource(name = "orderDao")  
  25.     public void setDao(BaseDao<Order> dao) {  
  26.         super.setDao(dao);  
  27.     }  
  28.   
  29.     /** 
  30.      * 若CustomerService 定義了BaseService沒有的方法,則可以在這裏實現 
  31.      */  
  32. }  

  

這裏只是提供了一個思路。可能代碼還有不嚴謹的地方,歡迎補充指正。

容易出現的兩個異常:

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:畫個圖好了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章