java Hibernate 通用 DAO、通用服务和通用视图层?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12099213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate generic DAO, Generic Service, and Generic View Layer?
提问by Curt
I have been trying to fully understand and implement a GenericDAO layer in hibernate. I am new to the concept and have been doing a bit of reading and studying. I have found numberous examples on example implementations of a GenericDAO Layer, and this is what I have ended up with.
我一直试图在休眠中完全理解和实现 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;
}
}
It seems as though this should work in theory (may need some tweaking)
似乎这在理论上应该有效(可能需要一些调整)
My question is can I use a generic service
and view layer
to "pass through" the layered architecture approach? I do not fully understand hibernate transactions enough to know if it is safe to do this, with its handling of transactions etc...
我的问题是我可以使用泛型service
并view layer
“通过”分层架构方法吗?我对休眠事务的理解不够充分,无法知道这样做是否安全,以及它对事务的处理等......
Maybe something like this for the service layer for example
例如,对于服务层,可能是这样的
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;
}
}
Then could I go on and do a generic view layer as well?
那么我可以继续做一个通用的视图层吗?
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!
在此先感谢您的想法和回复!
回答by EraMaX
I have implemented a Generic Entity, Dao and Service for Hibernate
我已经为 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
通用JpaDao
@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
用户DAO
public interface UserDAO extends GenericDao<User, Long> {
}
UserDAOImpl
用户DAOImpl
@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
最后是魔法服务我的服务 Mysv
@Service
public class Mysv extends GenericService<User, Long> {
}
回答by jeff
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.
就目前而言,您的服务只是将所有内容委托给底层 DAO。有时这可能是需要的,但通常我将“业务逻辑”放在服务层中。将逻辑放在服务层也将有助于保持您的控制器层相当轻巧。
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
一项服务可以使用一个或多个 DAO 来完成它需要的任务。所以考虑一个简单的银行系统,我有一个 AccountDao
public class AccountDao implements GenericDao<Account, Long> {
// your save, insert, delete, find, etc
}
Then in my service, I would put "makePayment" or something
然后在我的服务中,我会放“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);
}
}
Use transactions on your service layer, to give you more control over which operations need to be in the same transaction.
在您的服务层使用事务,让您更好地控制哪些操作需要在同一事务中。
回答by Neo182
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.
仅供参考,GenericDAO 有一个单独的代码库hibernate-generic-dao!为了学习而编写自己的代码总是好的,但我相信阅读标准库和框架的代码以学习专家已采用的标准也很重要。所以,推荐参观这个图书馆。