【问题标题】:Controller, Service, Repository and simple delegation methods控制器、服务、存储库和简单的委托方法
【发布时间】:2013-03-14 13:24:12
【问题描述】:

我有一个使用标准 spring/hibernate/jsp 堆栈和典型层的 Java EE 应用程序:

  • @Repository(或 DAO)
  • @服务
  • @Controller

每个存储库都有许多 find... 方法(例如,对于 BookRepository:简单的 findById、findByTitle、findByAuthor、更复杂的 findMostUsed、findMostCommented 等)

服务层包含应有的业务逻辑调用存储库。

控制器调用服务方法并填充要在 JSP 中使用的 ModelAndView。

当然,服务中也有一些具有复杂业务逻辑的方法。但是很烦人的是有很多这样的笨方法:

public List<Book> findMostUsed() {
    return repository.findMostUsed();
}
public List<Book> findMostCommented (boolean includeRating) {
    return repository.findMostCommented(includeRating);
}
...

所以它们只是一个简单的委托(这些查找方法中没有业务逻辑 - 存储库中的数据库查询完成所有选择和分组)。

如果我需要更改存储库中的方法,则服务也需要更改。经过 2 年的开发,无需为这些方法添加任何逻辑 - 仅更改了查询及其参数。

我看到过更糟糕的设计,人们创建了 Controller -> Facade -> Service -> Repository -> DAO,每一层都充满了这样的方法。

什么是更好的设计?

也许要删除所有这些方法并将服务转换为更通用(例如 BookPricingService、BookRatingService 等,而不是单个 BookService(这违反了单一职责原则)?然后控制器将调用服务和存储库层,即不好。

也许让 find 方法更通用,例如 findByCriteria(criteria) 以减少它们的数量。但问题是查询是如此不同,这将以一种 switch-case 块结束,该块根据条件类型选择正确的查询/参数。顺便说一句,Spring-Data 还建议每个带有 @Query 注释的查询使用一种方法。

也许这正是我们拥有抽象层应该付出的代价?

【问题讨论】:

    标签: spring jakarta-ee service repository


    【解决方案1】:

    对于这样的简单吸气剂,我只需将@Repository 直接注入我的@Controller 或在需要的地方@Service,并使用@Transactional(propagation = Propagation.REQUIRED) 注释存储库。该注释表明该方法必须在事务中使用,并且如果不存在则将创建一个(但如果已在事务中则不会创建第二个)。

    当操作多个根聚合/实体时,应使用服务类 - 即当有两种类型的存储库时。由于服务将一个工作单元所需的方法捆绑在一起,因此它们是同一事务的一部分。

    我也厌倦了不同的模式和依赖关系。

    我还使用标准查询和generics 来避免使用许多非常相似的方法,例如:

    @Transactional(readOnly = true)
        public <T> List<T> getFieldLike(String fieldName, String value) {
            final Session session = sessionFactory.getCurrentSession();
            final Criteria crit = session.createCriteria(genericType).add(Restrictions.ilike(fieldName, value, MatchMode.ANYWHERE));
            return crit.list();
        }
    
        @Transactional(readOnly = true)
        public <T> List<T> getFieldsEq( final Map<String, Object> restrictions) {
            final Session session = sessionFactory.getCurrentSession();
            final Criteria crit = session.createCriteria(genericType);
            for (final Map.Entry<String, Object> entry : restrictions.entrySet()) {
                crit.add(Restrictions.eq(entry.getKey(), entry.getValue()));
            }
            return crit.list();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多