访问数据库时分离问题的最佳做法

时间:2016-11-26 10:49:06

标签: java spring hibernate design-patterns

当涉及访问数据库的应用程序(通过Hibernate)时,我一直在努力改善关注点的分离。

在其中一个应用程序中,我一直在使用以下方法:

  • 使用没有数据库连接/感知的业务逻辑创建服务。他们只与GeneralDAO(以及其他服务)沟通;
  • 负责CRUD /查找操作的GeneralDAO,以及涉及更复杂数据库查询的方法。

我用这种方法看到的问题是:

  • 当您的应用程序增长并需要大量特定数据库查询时,GeneralDAO会慢慢成为God Object。
  • 有时,更具体的服务仅成为GeneralDAO的代理,因为该方法很简单,只需要数据库查询。见例1.

示例1:服务只是代理

BookService管理图书馆应用程序中与书籍相关的内容。让我们考虑两种方法:

  • archiveBook(书)
  • findByIsbn(String isbn)

archiveBook(Book)中可能涉及相当多的业务逻辑 - 我们可能会想到这涉及对:

的调用
 distributionService.unbox(Book);
 archivalBook.archive(Book);
 librarianService.informNewBook(Book);

但是findByIsbn(String isbn)要简单得多:它只需要对数据库执行SQL调用。所以在这种情况下,我看到两个选项:

  1. 将调用重定向到可以与数据库对话以执行查询的对象。例如generalDAO.findByIsbn(String isbn),它使用数据库通信层(在Hibernate中它将使用sessionFactory或EntityManager)来执行查询。
  2. 使该数据库层可供BookService使用,以便它自己执行查询
  3. 问题/意见(第一个数字标识上述选项):

    1.1。拥有完全相同签名的2个方法是不是很奇怪,即使这样做是为了保持BookService独立于数据库层(和ORM)?

    1.2。你如何建议避免上帝的反模式?你会建议将GeneralDAO分成几个DAO,具体取决于方法的作用吗?在这种情况下,我们不敢冒险将大量DAO注入某些服务,导致服务中注入了太多对象?

    2.1您如何看待这种替代方案?它没有打破"关注点的分离"让BookService知道两个不同抽象级别的对象(DAO和sessionFactory / EntityManager)?

    3.1。你会建议任何其他方法/模式/最佳实践吗?

    谢谢!

1 个答案:

答案 0 :(得分:1)

  

1.2。你如何建议避免上帝的反模式?你会建议根据具体情况将GeneralDAO分成几个DAO   方法呢?在这种情况下,我们不会冒很多需要注入的风险   DAO进入某些服务,导致服务具有太多对象   注入它?

通常,DAO类应该处理特定的实体 如果你的某个实体需要多种查询,你可以通过共同关注的方式将它们分成两个或多个DAO(例如:阅读,写作,选择agregates等等),如你所说。 /> 如果你有太多的查询和太多的DAO,也许,你应该检查你是否在几种方法中写了几乎相同的查询。在这种情况下,使用规范或Criteria API允许客户端通过参数进行自定义查询。如果查询确实不同,您可以进行各种处理。因此,使用多个DAO似乎是一个合适的解决方案。它避免增加神物的复杂性和兴起。

  

1.1。拥有完全相同签名的2个方法并不奇怪,即使这样做是为了保持BookService独立于   数据库层(和ORM)?

当您在逻辑层中划分应用程序时,正如您所注意到的,在某些操作中,某些层仅执行对下一层的委派调用。
因此在这些情况下,方法名称相同是很常见的。我会更进一步:如果只是委托调用,那么使用相同的名称是一个好习惯。如果它们都满足相同的需求,为什么我们会在传达的行为中创建一个变体?

  

2.1您如何看待这种替代方案?它没有打破"关注点的分离"让BookService知道对象   在两个不同的抽象层次(DAO和   的sessionFactory / EntityManager的)?

BookService依赖于DAO,但不应该依赖于构成DAO实现的sessionFactory / EntityManager。
BookService调用使用sessionFactory / EntityManager的DAO 如有必要,BookService可以使用@Transactional注释指定自身或其方法的事务详细信息。

  

3.1。你会建议任何其他方法/模式/最佳实践吗?

  • 当您使用Spring时,请尝试依赖Sping JPA存储库(较少的锅炉板来处理常见情况和可扩展类)
  • 如果您有多个查询的变体,请使用规范或条件模式。