1

我一直在尝试在休眠中完全理解和实现一个 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;
    }


}

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

Please let me know if this approach is acceptable or if there are any concerns with this approach.

Thanks in advance for your thoughts and responses!

4

3 回答 3

4

I have implemented a Generic Entity, Dao and Service for Hibernate

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


}

For Use :

User

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

}

And Finally the Magic Service my Service Mysv

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

}
于 2014-07-30T20:40:03.587 回答
3

Your service, as it stands, is simply delegating everything to the underlying DAO. This may be desired sometimes, but typically I put "business logic" in the service layer. Putting logic in the service layer will help keep your controller layer pretty light too.

A service can use one or more DAOs to accomplish the task it needs. So consider a simple bank system, where I have a AccountDao

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

Then in my service, I would put "makePayment" or something

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

Use transactions on your service layer, to give you more control over which operations need to be in the same transaction.

于 2012-08-23T20:32:09.640 回答
1

Just for your information, there exists a separate code library for GenericDAO hibernate-generic-dao! Its always good to write your own code for the purpose of learning, but I believe its also important to read code of standard libary and frameworks to learn standards that has been adopted there by experts. So, it is recommended to visit this library.

于 2014-09-01T13:13:45.123 回答