Hibernate 和 Spring - 道,服务
Posted
技术标签:
【中文标题】Hibernate 和 Spring - 道,服务【英文标题】:Hibernate and Spring - Dao ,Services 【发布时间】:2013-05-09 00:15:04 【问题描述】:我一直在阅读一些教程,我可以看到大多数 MVC 实现
基于:
1) 一个dao接口,例如“IUserDao”
2) 该接口的 dao impl - “mySimpleUserDaoImpl”
3) 持久化服务接口:“IUserService”
4) 和一个 impl - "UserServiceImpl"
这是最佳做法吗?我的意思是我问这个问题的原因是因为有 30 个服务与 getXById()、deleteX(x)、createX(x) 方法或多或少相同,这似乎是多余的。
请考虑到我使用的是 spring 3 和 hibernate 4,我决定在开始用代码敲击键盘之前先问这个问题
谢谢。
【问题讨论】:
您可以删除接口的I
前缀。用户不应该知道它正在获取一个界面。打电话给他们UserDAO
和UserService
。
同意,将 I 放在接口上。我个人称我的 Dao classes Repositories 只是为了使其与 Spring Annotations 保持一致,但这并不重要。
技术教程通常不涉及业务逻辑,因此它们不是很好的参考。 ***.com/q/3688664/217324有一个类似的问题可能对你有帮助
关于服务层的另一件事是你的@Transaction 应该从哪里开始。因此,如果您想跨多个存储库回滚事务,则可以在服务层执行此操作。这就是为什么服务应该与存储库是一对多的。
【参考方案1】:
如果您刚刚开始开发,请查看Spring JPA。服务应该是一对多存储库 (DAO)。但我也不会再手动创建所有样板代码。 Spring JPA 消除了基本的 CRUD 和搜索功能以及分页。
Here is a video 遍历 Spring、JPA、Hibernate 的所有配置,并以 Spring Data JPA 结束,向您展示所有已消除的样板代码。
要使用 Spring Data JPA,你的存储库接口最终是:
package com.mysampleapp.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.wcfgroup.model.Employee;
@Repository("employeeRepository")
public interface EmployeeRepository extends JpaRepository<Employee, Long>
Employee findBySsn(String ssn);
然后XML配置使用Spring Data JPA:
<jpa:repositories base-package="com.mysampleapp.repository"/>
现在为您处理所有样板代码。您不再需要创建具有查找方法和基本 CRUD 功能的基本存储库类。 JpaRepository
接口提供了许多不错的功能,您无需为实现做任何事情。
【讨论】:
关于服务层的另一件事是你的@Transaction 应该开始。因此,如果您想跨多个存储库回滚事务,则可以在服务层执行此操作。这就是为什么服务应该与存储库是一对多的。【参考方案2】:每个模型都必须有 dao、daoImpl、service、serviceImpl。
用户道 UserDaoImpl 用户服务 UserServiceImpl您可以使用通用类 EntityDaoImpl 和接口 EntityDao,如下所示:
实体道:
public interface EntityDao<E>
void persist(E e) throws Exception;
void remove(Object id) throws Exception;
E findById(Object id) throws Exception;
EntityDaoImpl:
public class EntityDaoImpl<E> implements EntityDao<E>
@PersistenceContext(unitName="UnitPersistenceName")
protected EntityManager entityManager;
protected E instance;
private Class<E> entityClass;
@Transactional
public void persist(E e) throws HibernateException
getEntityManager().persist(e);
@Transactional
public void remove(Object id) throws Exception
getEntityManager().remove((E)getEntityManager().find(getEntityClass(), id));
public E findById(Object id) throws Exception
return (E)getEntityManager().find(getEntityClass(), id);
public EntityManager getEntityManager()
return entityManager;
public void setEntityManager(EntityManager entityManager) throws Exception
this.entityManager = entityManager;
public Class<E> getEntityClass() throws Exception
if (entityClass == null)
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType)
ParameterizedType paramType = (ParameterizedType) type;
if (paramType.getActualTypeArguments().length == 2)
if (paramType.getActualTypeArguments()[1] instanceof TypeVariable)
throw new IllegalArgumentException(
"Can't find class using reflection");
else
entityClass = (Class<E>) paramType.getActualTypeArguments()[1];
else
entityClass = (Class<E>) paramType.getActualTypeArguments()[0];
else
throw new Exception("Can't find class using reflection");
return entityClass;
你可以这样使用:
public interface UserDao extends EntityDao<User>
和
public class UserDaoImpl extends EntityDaoImpl<User> implements UserDao
【讨论】:
所有这些代码本质上都是 Spring Data Jpa 为您提供的:springsource.org/spring-data/jpa 这段代码实际上有一些错误,你不想在 DAO/Repository 层开始你的事务。【参考方案3】:没有,没有必要有 30 个服务层或 30 个 dao 层。您应该指定层,而不是考虑实体,而是考虑业务功能。可以有 5 或 6 个与某些功能相关的实体,这些实体应该在一层。但是如果需要,您仍然必须在这些冗余层中拥有 getXById()、deleteX(x)、createX(x)。
【讨论】:
【参考方案4】:为每个模型创建单独的服务是实现此目的的一种方法,我已经看到了这样做的实际应用程序,但我不推荐这样做。这对于简单的 CRUD 案例来说是多余的,对于更复杂的案例(您实际上希望事务跨越多个 DAO 调用)没有帮助。它给你留下了很多无用的代码。可以使用 Spring Data 指定 DAO,服务将是样板文件,每个方法都包装对 DAO 的调用。 Spring 应该有助于减少样板文件,而不是强制它。
如果您有一个完全 CRUD 应用程序,那么您可以合法地不使用服务,将 @Transactional 放在 DAO 上,并从控制器调用 DAO。如果服务没有发挥作用,请摆脱它。
如果您在应用程序中确实有实际的业务逻辑,那么当用户调用可能涉及调用不同 DAO 的某些内容时,这些调用通常应该在同一个事务中进行,这样如果某件事失败,一切都会回滚。 (此外,创建事务相对昂贵,如果您有一个控制器为不同的实体调用不同的服务,那么这将很慢。)这就是服务派上用场的地方,服务指定用户想要的低级用例执行并允许指定事务行为。
对于 CRUD 案例,我更喜欢使用 Grails 或 Play 或 Rails 之类的工具,而不是使用 Spring MVC 编写 Java。例如,Grails 将为您生成视图和控制器,通过 GORM 提供基本的数据访问(因此无需编写 DAO),并且可以让您轻松地为您发现需要它们的情况指定服务。
【讨论】:
以上是关于Hibernate 和 Spring - 道,服务的主要内容,如果未能解决你的问题,请参考以下文章
Spring 和 Hibernate Restful web 服务配置
Hibernate 5.x和Spring Data 2.x:如何在服务保存方法中更新原始对象