英语原文共 24 页,剩余内容已隐藏,支付完成后下载完整资料
处理数据
本章内容
使用 Spring JdbcTemplate
使用 SimpleJdbcInsert 插入数据
使用 Spring Data 声明 JPA repositories
大多数应用程序提供的不仅仅是一张漂亮的脸。虽然用户界面可能提供与应用程序的交互,但它所呈现和存储的数据将应用程序与静态网站区分开来。
在 Taco Cloud 应用程序中,需要能够维护关于 ingredients、tacos 和 orders 的信息。如果没有一个数据库来存储这些信息,应用程序将无法比在第 2 章中开发的应用程序取得更大的进展。
在本章中,将向 Taco Cloud 应用程序添加数据持久化操作。首先使用 Spring 对 JDBC(Java Database Connectivity)的支持来消除样板代码。然后,将重新使用 JPA(Java Persistence API)处理数据存储库,从而消除更多代码。
3.1使用 JDBC 读写数据
几十年来,关系数据库和 SQL 一直是数据持久化的首选。尽管近年来出现了许多替代数据库类型,但关系数据库仍然是通用数据存储的首选,而且不太可能很快被取代。
在处理关系数据时,Java 开发人员有多个选择。两个最常见的选择是 JDBC 和 JPA。Spring 通过抽象支持这两种方式,这使得使用 JDBC 或 JPA 比不使用 Spring 更容易。在本节中,我们将重点讨论 Spring 是如何支持 JDBC 的,然后在第 3.2 节中讨论 Spring 对 JPA 的支持。
Spring JDBC 支持起源于 JdbcTemplate 类。JdbcTemplate 提供了一种方法,通过这种方法,开发人员可以对关系数据库执行 SQL 操作,与通常使用 JDBC 不同的是,这里不需要满足所有的条件和样板代码。
为了更好地理解 JdbcTemplate 的作用,我们首先来看一个示例,看看如何在没有 JdbcTemplate 的情况下用 Java 执行一个简单的查询。
程序清单 3.1 不使用 JdbcTemplate 查询数据库
@Override
public Ingredient findOne(String id) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement(
'select id, name, type from Ingredient');
statement.setString(1, id);
resultSet = statement.executeQuery();
Ingredient ingredient = null;
if(resultSet.next()) {
ingredient = new Ingredient(
resultSet.getString('id'),
resultSet.getString('name'),
Ingredient.Type.valueOf(resultSet.getString('type')));
}
return ingredient;
} catch (SQLException e) {
// ??? What should be done here ???
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {}
}
}
return null;
}
在程序清单 3.1 的某个地方,有几行代码用于查询数据库中的 ingredients。但是很难在 JDBC 的混乱代码中找到查询指针。它被创建连接、创建语句和通过关闭连接、语句和结果集来清理的代码所包围。
更糟糕的是,在创建连接或语句或执行查询时,可能会出现许多问题。这要求捕获一个 SQLException,这可能有助于(也可能无助于)找出问题出在哪里或如何解决问题。
SQLException 是一个被检查的异常,它需要在 catch 块中进行处理。但是最常见的问题,如未能创建到数据库的连接或输入错误的查询,不可能在 catch 块中得到解决,可能会重新向上抛出以求处理。相反,要是考虑使用 JdbcTemplate 的方法。
程序清单 3.2 使用 JdbcTemplate 查询数据库
private JdbcTemplate jdbc;
@Override
public Ingredient findOne(String id) {
return jdbc.queryForObject(
'select id, name, type from Ingredient where id=?',
this::mapRowToIngredient, id);
}
private Ingredient mapRowToIngredient(ResultSet rs, int rowNum)
throws SQLException {
return new Ingredient(
rs.getString('id'),
rs.getString('name'),
Ingredient.Type.valueOf(rs.getString('type')));
}
程序清单 3.2 中的代码显然比程序清单 3.1 中的原始 JDBC 示例简单得多;没有创建任何语句或连接。而且,在方法完成之后,不会对那些对象进行任何清理。最后,这样做不会存在任何在 catch 块中不能处理的异常。剩下的代码只专注于执行查询(调用 JdbcTemplate 的 queryForObject() 方法)并将结果映射到 Ingredient 对象(在 mapRowToIngredient() 方法中)。
程序清单 3.2 中的代码是使用 JdbcTemplate 在 Taco Cloud 应用程序中持久化和读取数据所需要做的工作的一个片段。让我们采取下一步必要的步骤来为应用程序配备 JDBC 持久话。我们将首先对域对象进行一些调整。
3.1.1 为域适配持久化
在将对象持久化到数据库时,通常最好有一个惟一标识对象的字段。Ingredient 类已经有一个 id 字段,但是需要向 Taco 和 Order 添加 id 字段。
此外,了解何时创建 Taco 以及何时放置 Order 可能很有用。还需要向每个对象添加一个字段,以捕获保存对象的日期和时间。下面的程序清单显示了 Taco 类中需要的新 id 和 createdAt 字段。
程序清单 3.3 向 Taco 类添加 id 和 timestamp 字段
@Data
public class Taco {
private Long id;
private Date createdAt;
...
}
因为使用 Lombok 在运行时自动生成访问器方法,所以除了声明 id 和 createdAt 属性外,不需要做任何事情。它们将在运行时根据需要生成适当的 getter 和 setter 方法。Order 类也需要做类似的修改,如下所示:
@Data
public class Order {
private Long id;
private Date placedAt;
...
}
同样,Lombok 会自动生成访问字段的方法,因此只需要按顺序进行这些更改。(如果由于某种原因选择不使用 Lombok,那么需要自己编写这些方法。)
域类现在已经为持久化做好了准备。让我们看看如何使用 JdbcTemplate 在数据中对它们进行读写。
3.1.2 使用 JdbcTemplate
在开始使用 JdbcTemplate 之前,需要将它添加到项目类路径中。这很容易通过添加 Spring Boot 的 JDBC starter 依赖来实现:
lt;dependencygt;
lt;groupIdgt;org.springframework.bootlt;/groupIdgt;
lt;artifactIdgt;spring-boot-starter-jdbclt;/artifactIdgt;
lt;/dependencygt;
还需要一个存储数据的数据库。出于开发目的,嵌入式数据库也可以。我喜欢 H2 嵌入式数据库,所以我添加了以下依赖进行构建:
lt;dependencygt;
lt;groupIdgt;com.h2databaselt;/groupIdgt;
lt;artifactIdgt;h2lt;/artifactIdgt;
lt;scopegt;runtimelt;/scopegt;
lt;/dependencygt;
稍后,将看到如何配置应用程序来使用外部数据库。但是现在,让我们继续编写一个获取和保存 Ingredient 数据的存储库。
定义 JDBC 存储库
Ingredient repository 需要执行以下操作:
- 查询所有的 Ingredient 使之变成一个 Ingredient 的集合对象
- 通过它的 id 查询单个 Ingredient
- 保存一个 Ingredient 对象
以下 IngredientRepository 接口将这三种操作定义为方法声明:
package tacos.data;
import tacos.Ingredient;
public interface IngredientRepository {
Iterablelt;Ingredientgt; findAll();
Ingredient findOne(String id);
Ingredient save(Ingredient ingredient);
}
尽管该接口体现了需要 Ingredient repository 做的事情的本质,但是仍然需要编写一个使用 JdbcTemplate 来查询数据库的 IngredientRepository 的实现。下面的程序清单是编写实现的第一步。
程序清单 3.4 使用 JdbcTemplate 开始编写 Ingredient repository
package tacos.data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import tacos.Ingredient;
@Repository
public class JdbcIngredientRepository
implements IngredientRepository {
private JdbcTemplate jdbc;
@Autowired
public JdbcIngredientRepository(JdbcTemplate jdbc) {
this.jdbc =
剩余内容已隐藏,支付完成后下载完整资料
资料编号:[411867],资料为PDF文档或Word文档,PDF文档可免费转换为Word
以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。