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