gpt4 book ai didi

spring - Controller、Service、Repository 和简单的委托(delegate)方法

转载 作者:行者123 更新时间:2023-12-02 03:48:32 27 4
gpt4 key购买 nike

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

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

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

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

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

当然,服务中也有一些方法和一些复杂的业务逻辑。但令人讨厌的是,有很多像这样的愚蠢方法:

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

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

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

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

什么是更好的设计?

也许删除所有这些方法并将服务转换为更通用(例如 BookPricingService、BookRatingService 等,而不是单一的 BookService(顺便说一句,这违反了单一职责原则)?然后 Controller 将同时调用 Service 和 Repository 层,这是不好。

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

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

最佳答案

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

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

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

我还使用 critera 查询和 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();
}

关于spring - Controller、Service、Repository 和简单的委托(delegate)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15410523/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com