在 Spring 应用中,有多种使用数据库的方式。我们可以使用 JPA 或 Hibernate 将对象映射为关系型数据库中的表和列。或者,我们干脆放弃关系型数据库,使用其他类型的数据库,如 Mongo 或 Neo4j。
对于 Contacts 应用来说,关系型数据库是不错的选择。我们将会使用 H2 数据库和 JDBC(使用 Spring 的 JdbcTemplate),让这个过程尽可能地简单。
选择这种方案就需要在构建中添加一些依赖。JDBC Starter 依赖会将 Spring JdbcTemplate 需要的所有内容都引入进来。不过,要结合使用 H2 数据库的话,我们还需要添加 H2 依赖。如果使用 Gradle 的话,在 dependencies 代码块添加如下两行代码就能完成这项任务:
compile("org.springframework.boot:spring-boot-starter-jdbc")
compile("com.h2database:h2")
如果使用 Maven 构建的话,我们需要如下的两个代码块:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
将这两项依赖添加到构建之中后,我们就可以编写 Repository 类了。如下程序清单中的 ContactRepository 将会使用注入的 JdbcTemplate 实现在数据库中读取和写入 Contact 对象。
程序清单 21.6 ContactRepository 能够从数据库中存取 Contact
package contacts;
import java.util.List;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
@Repository
public class ContactRepository {
private JdbcTemplate jdbc;
@Autowired
public ContactRepository(JdbcTemplate jdbc) {
this.jdbc = jdbc;
}
public List<Contact> findAll() {
return jdbc.query(
"select id, firstName, lastName, phoneNumber, emailAddress " +
"from contacts order by lastName",
new RowMapper<Contact>() {
public Contact mapRow(ResultSet rs, int rowNum) throws SQLException {
Contact contact = new Contact();
contact.setId(rs.getLong(1));
contact.setFirstName(rs.getString(2));
contact.setLastName(rs.getString(3));
contact.setPhoneNumber(rs.getString(4));
contact.setEmailAddress(rs.getString(5));
return contact;
}
}
);
}
public void save(Contact contact) {
jdbc.update(
"insert into contacts " +
"(firstName, lastName, phoneNumber, emailAddress) " +
"values (?, ?, ?, ?)",
contact.getFirstName(), contact.getLastName(),
contact.getPhoneNumber(), contact.getEmailAddress());
}
}
与 ContactController 类似,这个 Repository 类非常简单。它与传统 Spring 应用中的 Repository 类并没有什么差别。从实现中,根本无法看出它要用于 Spring Boot 的应用程序中。findAll() 方法使用注入的 JdbcTemplate 从数据库中获取 Contact 对象,save() 方法使用注入的 JdbcTemplate 保存新的 Contact 对象。因为 ContactRepository 使用了 @Repository 注解,因此在组件扫描的时候,它会被发现并创建为 Spring 应用上下文中的 bean。
但是,JdbcTemplate 呢?我们难道不需要在 Spring 应用上下文中声明 JdbcTemplate bean 吗?为了声明它,我们是不是还要声明一个 H2 DataSource?
对这两个问题的简短问答就是 “不需要”。当 Spring Boot 探测到 Spring 的 JDBC 模块和 H2 在类路径下的时候,自动配置就会发挥作用,将会自动配置 JdbcTemplate bean 和 H2DataSource bean。Spring Boot 再一次为我们处理了所有的 Spring 配置。
那数据库模式该怎么处理呢?我们必须要自己来定义创建 contacts 表的模式,对不对?
这绝对是正确的!Spring Boot 没有办法猜测 contacts 表会是什么样 子。所以,我们需要定义模式,如下所示:
create table contacts (
id identity,
firstName varchar(30) not null,
lastName varchar(50) not null,
phoneNumber varchar(13),
emailAddress varchar(30)
);
现在,我们只需要有一种方式加载这个 “create table” 的 SQL 并将其在 H2 数据库中执行就可以了。幸好,Spring Boot 也涵盖了这项功能。如果我们将这个文件命名为 schema.sql 并将其放在类路径根下 (也就是 Maven 或 Gradle 项目的 “src/main/resources” 目录下),当应用启动的时候,就会找到这个文件并进项数据加载。