写点什么

Hades——JPA 的开源实现

  • 2011-02-07
  • 本文字数:3979 字

    阅读完需:约 13 分钟

简介

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

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

查询

查询是使用最多的数据访问操作,如果你了解了 Hades,就会意识到查询作为 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);

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

引导 Hades

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

复制代码
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 工具套件的无缝集成,这样你就可以从其它 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" />

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

JPA 2.0 和事务性资源库

Hades2.0 是基于 JPA2.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 即可实现。想了解更多详细信息,请参考事务相关的参考文档。

规范

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

复制代码
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 是 VMware 公司的 SpringSource 部门的高级顾问,是 Hades 开源项目的项目主管。大约在两年前他在原公司 Synyx 启动了该项目。

查看英文原文: Hades - JPA Repositories Done Right


给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中 与我们的编辑和其他读者朋友交流。

2011-02-07 00:005819

评论

发布
暂无评论
发现更多内容

背完这套Java面试八股文,自动解锁面试牛逼症被动技能

Java你猿哥

MySQL redis java面试 java基础 分布式微服务

实例解读华为云数字工厂平台的逻辑模型编排器

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 5 月 PK 榜

GitHub上13个高赞Java项目推荐,会一个就能跟面试官谈笑风生

Java你猿哥

Java 微服务 秒杀系统 网约车项目 java项目

嘉为蓝鲸DevOps流水线工具如何为企业研发赋能?

嘉为蓝鲸

DevOps 流水线 蓝鲸

软件测试丨SeleniumIDE 自动化用例录制、测试用例结构分析

测试人

软件测试 自动化测试 测试开发 测试用例 selenium

开源赋能 普惠未来|铜锁/Tongsuo诚邀您参与2023开放原子全球开源峰会

开放原子开源基金会

开源

Velocity不用愁!Velocity系统的前端工程化之路 | 京东云技术团队

京东科技开发者

Java 前端工程化 Web H5 Velocity.js 企业号 5 月 PK 榜

我用ChatGPT,给RabbitMQ加了个连接池

Java你猿哥

Java 源码 ssm RabbitMQ ChatGPT

火山引擎多云安全平台,破解多云异构场景下的安全挑战

科技热闻

AntDB数据库参加开源数据库技术沙龙,分享全栈业务能力

亚信AntDB数据库

AntDB AntDB数据库 企业号 5 月 PK 榜

又爆神作!阿里首发并发编程神仙笔记,差距不止一点点

做梦都在改BUG

Java 并发编程

阿里SpringBoot实战手册横空出世!从此不再是易学难精

做梦都在改BUG

Java spring 微服务 Spring Boot 框架

还在服务器上捞日志?试试这款可视化监控系统吧,真香!

Java你猿哥

Java 日志 ssm 监控系统 Frostmourne

不吹不黑!阿里新产微服务架构进阶笔记我粉了!理论实战齐飞

做梦都在改BUG

Java 架构 微服务 Spring Cloud

使用 PAI-Blade 优化 Stable Diffusion 推理流程(二)

阿里云大数据AI技术

人工智能 优化 推理 Stable Diffusion 企业号 5 月 PK 榜

JMeter笔记7 | JMeter脚本回放

测试 Jmeter 性能测试 自动化测试 接口测试

云图说丨初识商标注册服务

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 5 月 PK 榜

胜面试官半子!阿里SpringBoot全栈笔记首发,源码实战齐飞

做梦都在改BUG

Java spring 微服务 Spring Boot 框架

为什么老有人想让我们“程序员”失业?征文获奖作品合集

InfoQ写作社区官方

技术专题合集 热门活动 三周年征文

嘉为蓝鲸CMP多云管理平台解决方案成功入选!

嘉为蓝鲸

多云管理 IT运维 蓝鲸

现代应用开发模式:PWA vs 小程序

Onegun

小程序 PWA

发挥数据价值!数据驱动的日志解析与异常检测方法介绍!

嘉为蓝鲸

日志分析 管理日志 日志统计

开源赋能 普惠未来|XuperCore诚邀您参与2023开放原子全球开源峰会

开放原子开源基金会

开源

浅谈财务共享未来发展趋势

用友BIP

业财融合 财务共享

40亿个QQ号,限制1G内存,如何去重?

Java你猿哥

Java ssm 布隆过滤器 BitMap 过滤器

涅槃重生!字节大牛力荐大型分布式手册,凤凰架构让你浴火成神

Java你猿哥

架构 Kubernetes 分布式 架构师 分布式架构

SpringBoot 中实现定时任务的几种方式

做梦都在改BUG

Java Spring Boot

理解JVM工作机制(二) 对象的创建

Geek漫游指南

Java JVM Java web

ps vs top:CPU占用率统计的两种不同方式

极限实验室

Linux 运维 监控系统 INFINI Console

百度工程师移动开发避坑指南——Swift语言篇

百度Geek说

swift 移动端 开发语言 企业号 5 月 PK 榜

Hades——JPA的开源实现_Java_Oliver Gierke_InfoQ精选文章