hades666_Hades-JPA存储库正确完成

hades666

介绍

世界上几乎所有的应用程序都必须访问数据以完成其工作。 使用域驱动的设计方法,您将需要定义和构建组成域的实体的存储库。 如今,Java开发人员经常使用JPA来实现这些存储库。 JPA使此任务更容易,但仍需要大量样板代码。 Hades是一个开放源代码库,它建立在JPA和Spring之上,可以通过减少实际所需的工作量来显着改善数据访问层的实现。 本文将带您进行导览,并概述了Hades在数据访问层开发方面实际上可以为您做些什么,并介绍了最新版本2.0的新功能。

Hades的核心部分包括一个通用的存储库实现,该实现不仅为您提供基本的CRUD(创建,读取,更新和删除)方法,而且还在顶部添加了一些功能,从而消除了围绕该通用实现的需求(例如分页)你自己 这包括查询存储库中的实体页面,动态添加排序定义等功能。

查询

由于您通常必须执行的大多数数据访问操作都是查询操作,所以Hades的核心功能之一就是以最小的努力轻松地定义和执行查询。 这样做的过程实际上包括三个步骤:

  1. 添加实体特定的存储库界面
  2. 添加查询方法
  3. 微调查询

在第一步中,您声明一个扩展GenericDao<Entity, Id>的接口,这将导致在Hades接口中定义的CRUD操作也可在您的接口上使用:

public interface UserRepository extends GenericDao<User, Long> { … }

下一步是将查询方法添加到满足您的业务需求的界面:

List findByUsername(String username);

这应该引起一个问题,即如何从该方法派生查询。 如果您不添加任何其他元数据,则Hades将尝试查找格式为{entity}.{method-name}的JPA命名查询,并在可用时使用它。 如果找不到任何内容,它将尝试解析方法名称并从中创建查询。 因此,前面的示例将导致查询select u from User u where u.username = ? 。 当然,查询解析器支持更多的关键字,因此可以随时在参考文档中进行查询

如果您希望手动定义查询,则可以利用Hades的@Query注释定义要直接在方法中执行的查询:

@Query("select from User u where u.lastname = ?");
List someReallyStrangeName(String lastname);

这使您可以自由选择自己喜欢的命名方法,同时保留对查询定义的完全控制,而不会打扰到样板查询执行代码。 执行查询还有很多其他方面, 例如对查询使用分页,执行修改查询等

自举阴霾

因此,既然您已经了解了如何使用查询方法创建存储库接口,那么如何开始并准备使用它们可能就很有趣了。 您可以通过创建GenericDaoFactory实例并要求其为您创建存储库来为存储库接口创建实例:

EntityManager em = … // Get access to EntityManager
GenericDaoFactory factory = GenericDaoFactory.create(em);
UserRepository userRepository = factory.getDao(UserRepository.class);

由于通常通过依赖项注入将存储库交给客户,因此Hades在Spring应用程序中的用法具有复杂的集成。 因此,要在Spring应用程序中引导Hades,您只需使用Hades命名空间并声明一个基本软件包,该基本软件包将被扫描以查找存储库。

<hades:dao-config base-package="com.acme.*.repository" />

这将获取扩展GenericDao所有存储库接口,并为每个接口创建Spring Bean。 当然,名称空间允许对要检测的内容进行更精细的控制Hades Eclipse插件提供了与Spring IDE和SpringSource Tool Suite(STS)的无缝集成,因此您将能够引用其他bean的Hades存储库,并在工作区中将它们标记为Spring bean。 有关详细信息,请查阅参考文档。

稽核

跟踪实体的创建者,修改者和相应日期是非常普遍的要求。 Hades提供了一个EntityListener ,它将透明地为您完成这项工作。 要激活Hades审核,您需要在orm.xml定义AuditingEntityListener

<persistence-unit-metadata>
  <persistence-unit-defaults>
    <entity-listeners>
      <entity-listener class="org.synyx.hades.domain.auditing.support.AuditingEntityListener" />
    </entity-listeners>
  </persistence-unit-defaults>
</persistence-unit-metadata>

然后在您的Spring配置中激活审核,如下所示:

<hades:auditing auditor-aware-ref="auditorAware" />

引用的Spring bean auditorAware必须实现AuditorAware接口,您通常会实现该接口来查询当前用户的安全模块。 如果只想跟踪创建和修改日期,则只需忽略该属性。 有关审核功能的更多信息, 请参阅文档。

JPA 2.0和事务存储库

从2.0版开始,Hades基于JPA 2.0以及相应版本的Hibernate,EclipseLink和OpenJPA。 从该版本开始,CRUD操作是开箱即用的事务,因此在非常简单的情况下,不再需要事务包装层。 此外,具体的存储库接口也可以轻松进行事务处理。

public interface UserRepository extends GenericDao<User, Long> {
  @Transactional(readOnly = true);
  List<User> findByUsername();

  @Override
  @Transactional(readOnly = true, timeout = 60);
  List<User> readAll();
}

如您所见,您可以使用@Transactional注释查询方法,以使它们参与事务。 如果您不愿意,则不必使用批注,基于XML的事务配置也可以正常工作。 默认情况下, GenericDao中实现的CRUD操作是事务性的(对于只读操作, readOnly设置为true)。 通过简单地重新声明方法并在其上应用自定义@Transactional即可完成为这些方法重新配置事务设置的操作。 有关更多详细信息,请参阅有关交易参考文档

技术指标

最新版本的一个很酷的功能是GenericDao的扩展,使其能够执行规范。 规范是由Eric Evans和Martin Fowler提出的领域驱动设计概念,可以归结为将实体的业务规则捕获为谓词。 Hades提供了一个抽象,可以轻松地基于JPA 2.0标准API构建此类谓词。 假设您有作家写的书。 Hades让您定义如下规格:

class BookSpecifications {
  public Specification<Book> hasAuthorWithFirstnameLike(final String firstname) {
    return new Specification<Book>() {
      public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
        return cb.like(root.join("author").get("firstname"), firstname);
      }
    }
  }

  public Specification<Book> hasGenre(final Genre genre) {
    return new Specification<Book>() {
      public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
        return cb.equal(root.get( "genre"), genre);
      }
    }
  }
}

诚然,这并不是要编写的最漂亮的代码(希望通过Java 8的单一抽象方法(SAM)功能,它会变得更好)。 从积极的方面来看,我们有可能在存储库中直接执行规范:

bookRepository.readAll(hasAuthorWithFirstnameLike("Oliv*"));

好的,这几乎是我们可以通过声明的查询实现的,对吗? 将规范组合到新规范中时,规范的威力真正闪耀。 Hades提供了一个Specifications助手类,该类允许即时合成:

bookRepository.readAll(where(hasAuthorWithFirstnameLike( "Oliv*").or(hasGenre(Genres.IT)));

这样,扩展您的存储库就成为添加新规范的问题。 拥有足够的规格,您将获得一个非常灵活的类似DSL的API,可以查询您的存储库,而不会为每种特殊情况使用查询方法污染存储库。 在文档中可以找到更详细的介绍

扩展名

2.0版本的另一部分是扩展模块,该模块无缝地将Hades与应用程序的上层技术(例如Spring MVC)集成。 它提供了一个PropertyEditor和Spring 3.0 Converter ,它可以通过实体的ID透明地将实体绑定到Spring MVC控制器方法,以及一个MVC扩展,可以从HTTP请求中动态提取分页信息。 因此,显示用户页面的控制器可能如下所示:

@Controller
class UserController {
  @Autowired
  UserRepository userRepository;

  @RequestMapping("/users")
  public void showUsers(Pageable pageable, Model model) {
    model.addAttribute("users", userRepository.readAll(pageable));
  }

  @RequestMapping("/users/{id}")
  public String showUser(@PathVariable("id") User user, Model model) {
    model.addAttribute("user", user);
    return"user";
  }
}

如您所见,对于showUsers(…)方法,不需要自己解析HttpServletRequest以获得分页信息。 注意,在showUser(…) ,绑定到id路径变量的方法参数已经是实体。 由于Spring MVC基础结构的配置超出了本文的范围,请随时查看扩展模块上的参考文档章节,其中提供了一些配置示例以简化设置

下一步是什么?

展望未来,Hades将超越2.1.x系列,成为Spring Data项目的一部分,其核心将作为其他数据存储库实现的基础。 Spring Data是一个SpringSource项目,旨在为各种新兴的专用数据存储(包括NoSQL数据库)提供惯用的Spring支持。

摘要

Hades极大地简化了使用JPA实施数据访问层的过程。 您可以免费获得复杂的CRUD操作,查询执行和规范。 它可以单独使用,但也可以与Spring很好地集成。 除此之外,还有一个Spring IDE / STS Eclipse插件以及一个Spring Roo插件,可以使用Roo轻松创建存储库。 有关更多信息, 请参见项目网站

翻译自: https://www.infoq.com/articles/hades_jpa_repositories_done_right/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

hades666

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值