Hibernate通用DAO,通用服务和通用视图层?

时间:2012-08-23 20:11:00

标签: java spring hibernate

我一直试图在hibernate中完全理解并实现GenericDAO层。我是这个概念的新手,并且一直在做一些阅读和学习。我已经在GenericDAO Layer的示例实现中找到了很多例子,这就是我最终得到的结果。

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来“通过”分层架构方法吗?我不完全了解hibernate事务,足以知道这样做是否安全,处理事务等...

对于服务层,例如

可能是这样的
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;
    }


}

然后我可以继续做一个通用的视图层吗?

如果这种方法可以接受或者对此方法有任何顾虑,请告诉我。

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

3 个答案:

答案 0 :(得分:4)

我已经为Hibernate实现了通用实体,Dao和服务

BaseEntity

@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();
    }

}

<强> GenericService

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;
    }
}

UserDAO

public interface UserDAO extends GenericDao<User, Long> {


}

UserDAOImpl

@Repository
public class UserDAOImpl extends GenericJpaDao<User, Long>  implements UserDAO {

    public UserDAOImpl() {
        super(User.class);
    }

    @PersistenceContext
    private EntityManager entityManager;

}

最后魔术服务我的服务Mysv

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

}

答案 1 :(得分:3)

现在,您的服务只是将所有内容委托给底层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);
   }
}

在服务层使用交易,让您更好地控制在同一交易中需要进行哪些操作。

答案 2 :(得分:1)

仅为了您的信息,GenericDAO hibernate-generic-dao存在单独的代码库!为了学习的目的,编写自己的代码总是很好,但我相信阅读标准库和框架的代码以学习专家采用的标准也很重要。因此,建议访问此库。