2013-03-14 40 views
2

我有使用弹簧的标准栈Java EE应用程序/休眠/ jsp和典型的层:控制器,服务,信息库和简单委派方法

  • @Repository(或DAO)
  • @Service
  • @Controller

每个仓库有很多找...方法(例如,用于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); 
} 
... 

所以他们只是一个简单的委托(有这些发现方法没有业务逻辑 - 库中一个DB查询执行所有选择和分组)。

如果我需要更改存储库中的方法,那么服务也需要更改。经过2年的开发,不需要为这些方法添加任何逻辑 - 只有查询及其参数发生了变化。

我看到了更糟糕的设计,人们用这样的方法创建了Controller - > Facade - > Service - > Repository - > DAO。

什么是更好的设计?

也许要删除所有这些方法并将服务转换为更通用的(例如BookPricingService,BookRatingService等,而不是单个BookService(违反单一职责原则btw)?那么Controller将调用Service和Repository图层这不是很好

也许可以使查找方法更通用,如findByCriteria(criteria)来减少它们的数量,但问题是查询是如此不同,这将以一种开关大小块结束根据标准类型选择正确的查询/参数Btw,Spring-Data还推荐使用@Query注释为每个查询提供一种方法

也许这只是我们应该支付的具有抽象层的价格?

回答

1

为简单的getter那样,我只是注入@Repository直入我的@Controller或在需要@Service,并与@Transactional(propagation = Propagation.REQUIRED)注释库。该annoatation incidcates该方法必须在事务中使用,并将创建一个(如果尚不存在),但不会创建第二个(如果已经在事务中)。

当正在操作多个根集合/实体时(即存在两种类型的存储库时),应该使用服务类。由于服务将所有工作单元所需的方法捆绑在一起,所以这些都是同一事务的一部分。

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

我也用性判据查询和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(); 
    }