# 第 11 章　使用对象-关系映射持久化数据

本章内容：

* 使用 Spring 和 Hibernate
* 借助上下文 Session，编写不依赖于 Spring 的 Repository
* 通过 Spring 使用 JPA
* 借助 Spring Data 实现自动化的 JPA Repository

小时候，骑自行车是一件很有趣的事情，对吧？在清晨，我们骑车上学。放学后，我们游逛到朋友家。当天色渐晚之时，在父母的呼喊声中，我们骑车回家。那些日子真的很有意思！

后来，随着慢慢长大，现在我们所需要的不仅仅是一辆自行车了。有时，我们需要走很远的路去上班或需要装载一些生活用品，还有可能接送孩子去上足球课。如果生活在得克萨斯州的话，我们还必须需要一台空调。我们的需求超出了自行车的功能范围。

在数据持久化的世界中，JDBC 就像自行车。对于份内的工作，它能很好地完成并且在一些特定的场景下表现出色。但随着应用程序变得越来越复杂，对持久化的需求也变得更复杂。我们需要将对象的属性映射到数据库的列上，并且需要自动生成语句和查询，这样我们就能从无休止的问号字符串中解脱出来。此外，我们还需要一些更复杂的特性：

* 延迟加载（*Lazy loading*）：随着我们的对象关系变得越来越复杂，有时候我们并不希望立即获取完整的对象间关系。举一个典型的例子，假设我们在查询一组 PurchaseOrder 对象，而每个对象中都包含一个 LineItem 对象集合。如果我们只关心 PurchaseOrder 的属性，那查询出 LineItem 的数据就毫无意义。而且这可能是开销很大的操作。延迟加载允许我们只在需要的时候获取数据。
* 预先抓取（*Eager fetching*）：这与延迟加载是相对的。借助于预先抓取，我们可以使用一个查询获取完整的关联对象。如果我们需要 PurchaseOrder 及其关联的 LineItem 对象，预先抓取的功能可以在一个操作中将它们全部从数据库中取出来，节省了多次查询的成本。
* 级联（*Cascading*）：有时，更改数据库中的表会同时修改其他表。回到我们订购单的例子中，当删除 Order 对象时，我们希望同时在数据库中删除关联的 LineItem。

一些可用的框架提供了这样的服务，这些服务的通用名称是对象/关系映射（object-relational mapping，ORM）。在持久层使用 ORM 工 具，可以节省数千行的代码和大量的开发时间。ORM 工具能够把你的注意力从容易出错的 SQL 代码转向如何实现应用程序的真正需求。

Spring 对多个持久化框架都提供了支持，包括Hibernate、iBATIS、Java 数据对象（Java Data Objects，JDO）以及 Java 持久化 API（Java Persistence API，JPA）。与 Spring 对 JDBC 的支持那样，Spring 对 ORM 框架的支持提供了与这些框架的集成点以及一些附加的服务：

* 支持集成 Spring 声明式事务；
* 透明的异常处理；
* 线程安全的、轻量级的模板类；
* DAO 支持类；
* 资源管理。

本章没有足够的篇幅介绍 Spring 支持的全部 ORM 框架。其实这并不会有什么问题，因为 Spring 对不同 ORM 解决方案的支持是很相似的。一旦掌握了 Spring 对某种 ORM 框架的支持后，你可以轻松地切换到另一个框架。

在本章中，我们将会看到 Spring 如何与最常用的两种 ORM 方案集成：Hibernate 和 JPA。同时还会通过 Spring Data JPA 了解一下 Spring Data 项目。借助这种方式，我们不仅可以学习到如何借助 Spring Data JPA 移除 JPA Repository 中的样板式代码，还能为下一章的如何将 Spring Data 用于无模式的存储打下基础。

让我们先来看看 Spring 是如何为 Hibernate 提供支持的。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://potoyang.gitbook.io/spring-in-action-v4/untitled-5.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
