【问题标题】:Hibernate generic DAO, Generic Service, and Generic View Layer?Hibernate 通用 DAO、通用服务和通用视图层?
【发布时间】:2012-08-23 20:11:00
【问题描述】:

我一直试图在休眠中完全理解和实现一个 GenericDAO 层。我对这个概念很陌生,并且一直在做一些阅读和研究。我在 GenericDAO 层的示例实现中找到了许多示例,这就是我最终得出的结论。

public class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> {

    private static Logger log = Logger.getLogger(GenericDAOImpl.class.getName());


    private SessionFactory sessionFactory;


    @SuppressWarnings("unchecked")
    public T findById(long id, Class<T> objectClass) {
        log.info("Entered GenericDAOImpl findById(" + id +")");
        T result = (T) getSessionFactory().getCurrentSession().load(objectClass, id);
        if(result != null){
            Hibernate.initialize(result);
            return result;
        }else{ 
            return null;
        }
    }

    public boolean create(T newInstance) {
        log.info("Entered GenericDAOImpl create()");
        if(newInstance == null){
            return false;
        }
        getSessionFactory().getCurrentSession().saveOrUpdate(newInstance);
        return true;        
    }


    public boolean updpate(T updateInstance) {
        log.info("Entered GenericDAOImpl updpate()");
        if(updateInstance == null){
            return false;
        }
        getSessionFactory().getCurrentSession().update(updateInstance); 
        return true;
    }

    public boolean delete(T entity) {
        log.info("Entered GenericDAOImpl delete()");
        if(entity == null){
            return false;
        }
        getSessionFactory().getCurrentSession().delete(entity);
        return true;
    }

    @SuppressWarnings("unchecked")
    public List<T> findByExample(T exampleInstance, Class<T> objectClass){
        log.info("Entered GenericDAOImpl findByExample()");
        Criteria searchCriteria = getSessionFactory().getCurrentSession().createCriteria(objectClass);

        searchCriteria.add(Example.create(exampleInstance));

        return (List<T>)searchCriteria.list();          

    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }       
}

这似乎在理论上应该可行(可能需要一些调整)

我的问题是我可以使用通用的serviceview layer 来“通过”分层架构方法吗?我对休眠事务的理解不够充分,无法知道这样做是否安全,以及它对事务的处理等......

例如对于服务层可能是这样的

public class GenericServiceImpl<T, ID extends Serializable> implements GenericService<T, ID>{

    private GenericDAO<T, ID> genericDao;

    @Override
    public T findById(long id, Class<T> objectClass) {
        return this.getGenericDao().findById(id, objectClass);
    }

    @Override
    public boolean create(T newInstance) {
        return this.getGenericDao().create(newInstance);
    }

    @Override
    public boolean updpate(T updateInstance) {
        return this.getGenericDao().updpate(updateInstance);
    }

    @Override
    public boolean delete(T entity) {
        return this.getGenericDao().delete(entity);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public List findByExample(T exampleInstance, Class<T> objectClass) {
        return this.getGenericDao().findByExample(exampleInstance, objectClass);
    }


    public GenericDAO<T, ID> getGenericDao() {
        return genericDao;
    }

    public void setGenericDao(GenericDAO<T, ID> genericDao) {
        this.genericDao = genericDao;
    }


}

那我可以继续做一个通用视图层吗?

请让我知道这种方法是否可以接受或对这种方法有任何顾虑。

提前感谢您的想法和回复!

【问题讨论】:

    标签: java spring hibernate


    【解决方案1】:

    我已经为 Hibernate 实现了一个通用实体、Dao 和服务

    基础实体

    @MappedSuperclass
    public class BaseEntity implements Serializable {
    
        private static final long serialVersionUID = -932093556089251203L;
    
        @Id
        @GeneratedValue
        private Long id;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
    }
    

    GenericDao

    public interface GenericDao<T, ID extends Serializable> {
    
        T save(T entity);
        T update(T entity);
        void delete(T entity);
        T findById(long id);
        List<T> findAll();
        void flush();
    }
    

    GenericJpaDao

    @Transactional
    public abstract class GenericJpaDao<T, ID extends Serializable> implements GenericDao<T, ID> {
    
        private Class<T> persistentClass;
    
        @PersistenceContext
        private EntityManager entityManager;
    
        public GenericJpaDao(Class<T> persistentClass) {
            this.persistentClass = persistentClass;
        }
    
        protected EntityManager getEntityManager() {
            return entityManager;
        }
    
        @PersistenceContext
        public void setEntityManager(EntityManager entityManager) {
            this.entityManager = entityManager;
        }
    
        public Class<T> getPersistentClass() {
            return persistentClass;
        }
    
        @Transactional(readOnly=true)
        public T findById(long id) {
            T entity = (T) getEntityManager().find(getPersistentClass(), id);
            return entity;
        }
    
        @SuppressWarnings("unchecked")
        @Transactional(readOnly=true)
        public List<T> findAll() {
            return getEntityManager()
                .createQuery("select x from " + getPersistentClass().getSimpleName() + " x")
                .getResultList();
        }
    
        public T save(T entity) {
            getEntityManager().persist(entity);
            return entity;
        }
    
        public T update(T entity) {
            T mergedEntity = getEntityManager().merge(entity);
            return mergedEntity;
        }
    
        public void delete(T entity) {
            if (BaseEntity.class.isAssignableFrom(persistentClass)) {
                getEntityManager().remove(
                        getEntityManager().getReference(entity.getClass(), 
                                ((BaseEntity)entity).getId()));
            } else {
                entity = getEntityManager().merge(entity);
                getEntityManager().remove(entity);
            }
        }
    
        public void flush() {
            getEntityManager().flush();
        }
    
    }
    

    通用服务

    public class GenericService<T, ID extends Serializable> {
        @Autowired
        private GenericDao<T, ID> genericDao;
    
        public T find(long id) {
            return this.getGenericDao().findById(id);
        }
    
        public List<T> all() {
            return this.getGenericDao().findAll();
        }
    
        @Transactional
        public T create(T newInstance) {
            return (T) this.getGenericDao().save(newInstance);
        }
    
        @Transactional
        public T updpate(T updateInstance) {
            return (T) this.getGenericDao().update(updateInstance);
        }
    
        @Transactional
        public void delete(T entity) {
             this.getGenericDao().delete(entity);
        }
    
        public GenericDao<T, ID> getGenericDao() {
            return genericDao;
        }
    
        public void setGenericDao(GenericDao<T, ID> genericDao) {
            this.genericDao = genericDao;
        }
    
    
    }
    

    供使用:

    用户

    @Entity
    @Table(name="USER")
    public class User extends BaseEntity {
    
        private static final long serialVersionUID = -6189512849157712745L;
    
        @Column(name="username", nullable = false)
        private String username;
    
        @Column(name="name", nullable = false)
        private String name;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    用户DAO

    public interface UserDAO extends GenericDao<User, Long> {
    
    
    }
    

    用户DAOImpl

    @Repository
    public class UserDAOImpl extends GenericJpaDao<User, Long>  implements UserDAO {
    
        public UserDAOImpl() {
            super(User.class);
        }
    
        @PersistenceContext
        private EntityManager entityManager;
    
    }
    

    最后是 Magic Service my Service Mysv

    @Service
    public class Mysv extends GenericService<User, Long> {
    
    }
    

    【讨论】:

      【解决方案2】:

      就目前而言,您的服务只是将所有内容委托给底层 DAO。有时这可能是需要的,但通常我将“业务逻辑”放在服务层中。将逻辑放入服务层也有助于保持控制器层的简洁性。

      服务可以使用一个或多个 DAO 来完成它需要的任务。所以考虑一个简单的银行系统,我有一个 AccountDao

      public class AccountDao implements GenericDao<Account, Long> {
        // your save, insert, delete, find, etc
      }
      

      然后在我的服务中,我会输入“makePayment”之类的东西

      @Service
      public class AccountService {
      
         @Autowired
         private AccountDao dao;
      
         @Transactional
         public void makePayment(Long fromId, Long toId, double amount) {
            Account from = dao.find(fromId);
            from.withdrawl(amount);
      
            Account to = dao.find(toId);
            to.deposit(amount);
      
            dao.save(from);
            dao.save(to);
         }
      }
      

      在您的服务层使用事务,让您更好地控制哪些操作需要在同一个事务中。

      【讨论】:

      • 感谢您的快速回复!所以为了澄清,您仍然会为每个简单实现或扩展 GenericDAO 的休眠域对象创建一个单独的 DAO?我创建 genericDAO 的全部目的是减少冗余休眠 DAO 类的数量?
      • 如果您的数据库操作如此简单(只是更新、插入、删除)并且没有专门的查询,那么您只需实例化几个通用 daos,每种类型一个。
      【解决方案3】:

      仅供参考,GenericDAO hibernate-generic-dao 有一个单独的代码库!出于学习的目的编写自己的代码总是好的,但我相信阅读标准库和框架的代码以学习专家采用的标准也很重要。所以,推荐去这个图书馆。

      【讨论】:

        猜你喜欢
        • 2018-01-10
        • 2014-12-04
        • 2012-03-15
        • 1970-01-01
        • 2016-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多