Hades :Java语言术语

更新时间:2024-09-20 17:35

Hades是一个开源库,基于JPA和Spring构建,通过减少开发工作量显著的改进了数据访问层的实现。其可以大大简化了使用JPA执行数据层的访问过程,使用户可以自由的进行精确的CRUD操作、执行查询和规范等。

开源实现

几乎每个应用系统都需要通过访问数据来完成工作。要想使用领域设计方法,你就需要为实体类定义和构建资源库来实现领域对象的持久化。目前开发人员经常使用JPA来实现持久化库。JPA让持久化变得非常容易,但是仍然需要编写很多模板代码。Hades是一个开源库,基于JPA和Spring构建,通过减少开发工作量显著的改进了数据访问层的实现。本文是Hades的向导性教程,会带你走进Hades的世界,帮助你了解Hades在数据持久化方面能为你做些什么,并简要介绍了最新的2.0版本的新特性。

Hades的核心部分由通用的持久化库实现构成,不仅提供了基本的CRUD(增删改读)方法,而且增加了一些通用场景功能的实现,类似分页这样的功能你就不用自己实现了。还包括查询实体页、动态增加排序定义等能力。

查询

查询是使用最多的数据访问操作,如果你了解了Hades,就会意识到查询作为Hades的核心功能之一,定义和执行查询是多么容易,大大减少了工作量。一般完成一个查询操作包括以下三个步骤:

1.增加特定实体的库接口

2.增加查询方法

3.微调查询

首先你需要声明一个继承了GenericDao\u003cEntity, Id\u003e的接口,该类保证在Hades接口中定义的CRUD方法在你的接口中是有效的,如下:

public interface UserRepository extends GenericDao\u003cUser, Long\u003e { … }

其次是根据业务需求为你的接口增加查询方法:

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);

这样你可以自由的进行方法命名,既可以对查询定义实现完全控制,又不必担心那些查询模板代码。围绕着执行查询还有很多方式,例如使用分页查询、执行编辑查询等。

引导Hades

到目前为止我们已经讨论了如何创建带有查询方法的库接口,接下来我们看一下如何使用这些接口。首先创建实体类的实例,然后根据该实例创建GenericDaoFactory的实例,通过工厂实例的getDao方法创建你需要的资源库,如下代码所示:

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

由于资源库经常通过依赖注入的方式被其客户端持有,所以Hades提供了优雅的方式与与Spring应用集成。在Spring的应用中引导Hades非常简单,只需使用Hades的命名空间,并声明可以被匹配到的基础包即可:

\u003chades:dao-config base-package="com.acme.*.repository" /\u003e

以上配置方式会选中所有继承了GenericDao的资源库接口,并为每个接口创建Spring的Bean。当然,命名空间支持更细粒度的配置,以实现精确控制。Hades的Eclipse插件实现了与Spring IDE和SpringSource工具套件的无缝集成,这样你就可以从其它Bean引用Hades的资源库,并在你的工作空间把它们标记为Spring的Bean。想了解详细信息请查看其参考手册。

审计

在系统中记录实体类的创建者、修改者和相关日期等信息是一个很常见的需求。Hades提供了监听器EntityListener,可以帮你透明的实现这些功能。要启用Hades的审计功能,只需要在orm.XML文件中定义AuditingEntityListener即可:

\u003cpersistence-unit-metadata\u003e \u003cpersistence-unit-defaults\u003e \u003centity-listeners\u003e \u003centity-listener class="org.synyx.hades.domain.auditing.support.AuditingEntityListener" /\u003e \u003c/entity-listeners\u003e \u003c/persistence-unit-defaults\u003e\u003c/persistence-unit-metadata\u003e

并在Spring的配置中启动审计功能,如下:

\u003chades:auditing auditor-aware-ref="auditorAware" /\u003e

auditorAware是引用的Spring Bean,需要实现AuditorAware接口,通常是实现针对当前用户的安全查询功能。如果你只想跟踪创建和编辑日期,只需忽略该属性即可。想了解更多审计特性,请参考相关文档。

资源库

Hades2.0 是基于JPA2.0以及相关的Hibernate、EclipseLink和OpenJPA版本构建的。基于该版本的CRUD事务操作使用非常简单,开箱即用,对于相对简单的场景基本不需要再进行事务性的封装。未来结合资源库接口可以让事务管理变得更加简单。

public interface UserRepository extends GenericDao\u003cUser, Long\u003e { @Transactional(readOnly = true); List\u003cUser\u003e findByUsername(); @Override @Transactional(readOnly = true, timeout = 60); List\u003cUser\u003e readAll();}

正如你看到的,你可以简单的通过为查询方法增加注释@Transactional的方式把它们加入事务。当然,也可以不用注释的方式,基于XML的事务配置也能运行的很好。在GenericDao中的CRUD操作具备默认的事务性(对只读操作来说就是把readOnly设置为true)。如果你想为这些方法重新配置事务,简单的为这些方法声明自定义的@Transactional即可实现。想了解更多详细信息,请参考事务相关的参考文档。

规范

Hades 最新版本的一个非常酷的特性是基于GenericDao的扩展即可符合规范。这里提到的规范指领域驱动设计的概念,DDD是由Eric Evans和Martin Fowler首次提出,从本质上捕捉实体的业务规则的一种开发方法。Hades提供的抽象方式可以很容易的基于JPA2.0的标准API实现领域驱动设计。在这里我们假设你已经读过上面提到的两位作者写的DDD相关的书籍。Hades提供了如下方式定义规范:

class BookSpecifications { public Specification\u003cBook\u003e hasAuthorWithFirstnameLike(final String firstname) { return new Specification\u003cBook\u003e() { public Predicate toPredicate(Root\u003cBook\u003e root, CriteriaQuery\u003c?\u003e cq, CriteriaBuilder cb) { return cb.like(root.join("author").get("firstname"), firstname); } } } public Specification\u003cBook\u003e hasGenre(final Genre genre) { return new Specification\u003cBook\u003e() { public Predicate toPredicate(Root\u003cBook\u003e root, CriteriaQuery\u003c?\u003e cq, CriteriaBuilder cb) { return cb.equal(root.get( "genre"), genre); } } }}

当然,这并不是最优雅的代码片段(如果未来与Java 8里的单抽象方法(SAM)特性结果结合的话,效果会更好)。从积极的方面考虑,我们在资源库层面获得了执行规范的可能性:

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

好了,我们在声明式查询方面已经做了很多,不是吗?规范的能力真正闪光的时候是把它们整合为新的规范的时候。Hades提供了规范助手类,可以进行任意的合并:

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

通过这种方式,扩展资源库就变成了只是增加新的规范。少量的规范就可以帮助你使用类似DSL的柔性API查询资源库,而不是针对每次外部查询请求都使用查询方法访问资源库。想了解更多详细信息,请参考相关文档。

扩展

2.0 版本的另一部分内容是扩展模块,可以实现Hades与展现层技术框架(例如Spring的MVC)的无缝集成。它提供了属性编辑器和Spring 3.0转换器,可以透明的把实体类与MVC控制器方法的绑定在一起,同时MVC扩展还可以动态的从HTTP请求中提取分页信息。一个展示用户列表的页面,在控制层的写法就是这样:

@Controllerclass 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基础框架的配置内容已经超出了本文要讨论的范围,如果想了解更多信息,请参考扩展模块配置信息的相关章节,其中提供了非常容易的设置样例。

下一步

展望未来,2.1.x版本之后,Hades可能会成为Spring Data项目的一部分,其核心将作为实现其它数据存储资源库的实现基础。Spring Data是SpringSource的项目,其目标是为新兴的数据库、特定的数据存储提供Spring的方言支持,包括NoSQL数据库。

总结

Hades 大大简化了使用JPA执行数据层的访问过程。你可以自由的进行精确的CRUD操作、执行查询和规范等。Hades既可以独立使用,可以方便的集成到 Spring中。除此之外,Eclipse插件Spring IDE/STS和附加的Spring Roo 都可以非常容易的创建资源库。想了解更多信息,请参考项目网站。

关于作者

Oliver Gierke是威睿公司的SpringSource部门的高级顾问,是Hades开源项目的项目主管。大约在两年前他在原公司Synyx启动了该项目。

参考资料

免责声明
隐私政策
用户协议
目录 22
0{{catalogNumber[index]}}. {{item.title}}
{{item.title}}
友情链接: