如何改进这种分层架构?

时间:2014-03-20 22:18:52

标签: java spring jpa spring-data software-design

在我的工作中,我们遵循这种分层架构:http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

我们有以下内容:

Maven数据库项目

Spring Data Repositories - 运行自定义SQL的自定义@Query方法 数据库服务 - 调用存储库接口以保留或从数据库中获取JPA模型数据 JPA模型 - 包含我们的Hibernate JPA模型,它们只有getter和setter

Maven Common Project

DAO - 调用数据库服务来获取数据并将它们转换为DTO对象或将我们的DTO对象转换为JPA模型以传递给数据库服务以保存
Business Objects(BO) - 包含我们的业务逻辑并调用DAO来保存或获取数据(DTO) DTO - 与JPA模型相同,但具有可能不在数据库中的属性

依赖Maven Common Project的项目

这些项目有不同的目的:
- 一个项目是内部支持工具 - 另一个是我们客户的监控工具 - 另一种是推动业务目的的自定义引擎

问题

我对这个架构的问题是,如果我想将一个新功能(如getMostRecentOrder())添加到依赖于我们的Common项目的模块中,我必须创建4个方法而不是1.我们还有另一个层用于我们的一个应用程序当工程师不想要/不需要知道它时,它会抽象Spring,这会产生5种方法。

是否有人遵循类似这样的分层架构并能够解决或找到更好的解决方案?

我工作的架构师喜欢这种结构,但我开始真的不喜欢它,因为添加所有这些方法只是为了获取数据,这似乎很繁琐似乎我正在编写大量重复代码由于存在的图层,数据类型会发生变化。

架构师希望我们的BO像WeatherBO一样具有通用性,它具有天气的所有业务逻辑,EventBO用于事件的所有逻辑等等。我的问题是我们的BO开始是1000行代码,我感觉我们上大班时郁闷。

任何人都可以提供一些成功的Java分层架构的一些见解,这些架构很简单(3层与我的4或5层),可维护,灵活,可扩展等(基本上是开发人员的头号梦想哈哈)?< / p>

更新: 提供图层的伪代码

存储库

public interface IOrderRepository extends JpaRepository {
       @Query("FROM Order o WHERE o.time = Max Time")
       Order getMostRecentOrder();
}

数据库服务

 public interface IOrderService extends IService<Entity ID, Entity> {
        Order getMostRecentOrder();
 }

 @Service
 @Transactional
 public final class OrderServiceImpl implements IOrderService {
      @Autowired
      private IOrderRepository repository;          

      @Override
      public Order getMostRecentOrder() {
           return repository.getMostRecentOrder();
      }
 }

DAO

 public interface IOrderDAO extends IDAO<DTO Key, DTO> {
      OrderDTO getMostRecentOrder();
 }

 @Service
 @Transactional
 public final class OrderDAOImpl implements IOrderDAO {
      @Autowired
      private IOrderService service;
      // Spring Conversion Service that uses Dozer to convert JPA model to DTO
      @Autowired
      private ConversionService conversionService;

      @Override
      public OrderDTO getMostRecentOrder() {
          Order order = service.getMostRecentOrder();
          return conversionService.convert(order, OrderDTO.class);
      }
 }

BO

 @Service
 public final class OrderBO {
     @Autowired
     private IOrderDAO orderDAO;

     public OrderDTO getMostRecentOrder() {
        return orderDAO.getMostRecentOrder();
     }
 }

网络服务电话

 @PATH("/orders")
 @Service
 public class OrderResource {

     @Autowired
     private OrderBO orderBO;

     @GET
     @PATH("/getMostRecentOrder")
     @Produces(APPLICATION_JSON)
     public Response getMostRecentOrder() {
        Response response = Response.ok().build();
        OrderDTO orderDTO = orderBO.getMostRecentOrder();
        response.withEntity(orderDTO).build();
        return response;
     }
 }

这只是一个例子,但BO比我提供的示例大得多,而且有近1000行代码或者关闭。另外我担心DAO也会变得很大。我们为每个DTO和JPA模型都有一个DAO,服务和存储库。 BO通常是常见DAO的集合,例如,OrderBO可以有订单DAO,发票DAO,客户DAO等。

1 个答案:

答案 0 :(得分:1)

我不认为这里有正确或错误的答案,但我通常做的是......

我要创建一个“数据库”项目。该项目将包含所有数据库交互。

然后我创建一个“服务”项目,该项目将包含所有业务/服务操作。这个也直接与“数据库”项目交互。该项目将公开所有业务方法,如saveClient(客户端客户端),deleteClient(客户端客户端),updateProjects(列表项目)等。

然后我创建N个“客户端”项目,而不是与调用接口方法的“服务”项目交互。

只是几个旁注。 1-客户端是客户端应用程序,如Web应用程序或桌面或移动应用程序。它们都“可以/应该”根据要求与同一服务层进行交互。 2-这是概念性概述。

我尽量保持一切标准。 但是,您的“抱怨”是,如果您有一个新的“客户”要求,例如“按特定顺序显示项目”,则需要3或4个新方法。是的,您需要编写3或4种新方法,具体取决于您拥有的层数。我记得使用整个J2EE堆栈的项目,其中一个简单的CRUD操作需要来自DAO,外墙,拦截器和其他几个类的12个类。

就个人而言,我尝试遵循KISS principle