Spring 实战(第四版)
  • Spring 实战(第 4 版)
  • 第一部分 Spring 的核心
  • 第 1 章 Spring 之旅
    • 1.1 简化 Java 开发
      • 1.1.1 激发 POJO 的潜能
      • 1.1.2 依赖注入
      • 1.1.3 应用切面
      • 1.1.4 使用模板消除样式代码
    • 1.2 容纳你的 Bean
      • 1.2.1 使用应用上下文
      • 1.2.2 bean 的生命周期
    • 1.3 俯瞰 Spring 风景线
      • 1.3.1 Spring 模块
      • 1.3.2 Spring Portfolio
    • 1.4 Spring 的新功能
      • 1.4.1 Spring 3.1 新特性
      • 1.4.2 Spring 3.2 新特性
      • 1.4.3 Spring 4.0 新特性
    • 1.5 小结
  • 第 2 章 装配 Bean
    • 2.1 Spring 配置的可选方案
    • 2.2 自动化装配 bean
      • 2.2.1 创建可被发现的 bean
      • 2.2.2 为组件扫描的 bean 命名
      • 2.2.3 设置组件扫描的基础包
      • 2.2.4 通过为 bean 添加注解实现自动装配
      • 2.2.5 验证自动装配
    • 2.3 通过 Java 代码装配 bean
      • 2.3.1 创建配置类
      • 2.3.2 声明简单的 bean
      • 2.3.3 借助 JavaConfig 实现注入
    • 2.4 通过 XML 装配 bean
      • 2.4.1 创建 XML 配置规范
      • 2.4.2 声明一个简单的 <bean>
      • 2.4.3 借助构造器注入初始化 bean
      • 2.4.4 设置属性
    • 2.5 导入和混合配置
      • 2.5.1 在 JavaConfig 中引用 XML 配置
      • 2.5.2 在 XML 配置中引用 JavaConfig
    • 2.6 小结
  • 第 3 章 高级装配
    • 3.1 环境与 profile
      • 3.1.1 配置 profile bean
      • 3.1.2 激活 profile
    • 3.2 条件化的 bean
    • 3.3 处理自动装配的歧义性
      • 3.3.1 标示首选的 bean
      • 3.3.2 限定自动装配的 bean
    • 3.4 bean 的作用域
      • 3.4.1 使用会话和请求作用域
      • 3.4.2 在 XML 中声明作用域代理
    • 3.5 运行时值注入
      • 3.5.1 注入外部的值
      • 3.5.2 使用 Spring 表达式语言进行装配
    • 3.6 小结
  • 第 4 章 面向切面的 Spring
    • 4.1 什么是面向切面编程
      • 4.1.1 定义 AOP 术语
      • 4.1.2 Spring 对 AOP 的支持
    • 4.2 通过切点来选择连接点
      • 4.2.1 编写切点
      • 4.2.2 在切点中选择 bean
    • 4.3 使用注解创建切面
      • 4.3.1 定义切面
      • 4.3.2 创建环绕通知
      • 4.3.3 处理通知中的参数
      • 4.3.4 通过注解引入新功能
    • 4.4 在 XML 中声明切面
      • 4.4.1 声明前置和后置通知
      • 4.4.2 声明环绕通知
      • 4.4.3 为通知传递参数
      • 4.4.4 通过切面引入新的功能
    • 4.5 注入 AspectJ 切面
    • 4.6 小结
  • 第二部分 Web 中的 Spring
  • 第 5 章 构建 Spring Web 应用程序
    • 5.1 Spring MVC 起步
      • 5.1.1 跟踪 Spring MVC 的请求
      • 5.1.2 搭建 Spring MVC
      • 5.1.3 Spittr 应用简介
    • 5.2 编写基本的控制器
      • 5.2.1 测试控制器
      • 5.2.2 定义类级别的请求处理
      • 5.2.3 传递模型数据到视图中
    • 5.3 接受请求的输入
      • 5.3.1 处理查询参数
      • 5.3.2 通过路径参数接受输入
    • 5.4 处理表单
      • 5.4.1 编写处理表单的控制器
      • 5.4.2 校验表单
    • 5.5 小结
  • 第 6 章 渲染 Web 视图
    • 6.1 理解视图解析
    • 6.2 创建 JSP 视图
      • 6.2.1 配置适用于 JSP 的视图解析器
      • 6.2.2 使用 Spring 的 JSP 库
    • 6.3 使用 Apache Tiles 视图定义布局
      • 6.3.1 配置 Tiles 视图解析器
    • 6.4 使用 Thymeleaf
      • 6.4.1 配置 Thymeleaf 视图解析器
      • 6.4.2 定义 Thymeleaf 模板
    • 6.5 小结
  • 第 7 章 Spring MVC 的高级技术
    • 7.1 Spring MVC 配置的替代方案
      • 7.1.1 自定义 DispatcherServlet 配置
      • 7.1.2 添加其他的 Servlet 和 Filter
      • 7.1.3 在 web.xml 中声明 DispatcherServlet
    • 7.2 处理 multipart 形式的数据
      • 7.2.1 配置 multipart 解析器
      • 7.2.2 处理 multipart 请求
    • 7.3 处理异常
      • 7.3.1 将异常映射为 HTTP 状态码
      • 7.3.2 编写异常处理的方法
    • 7.4 为控制器添加通知
    • 7.5 跨重定向请求传递数据
      • 7.5.1 通过 URL 模板进行重定向
      • 7.5.2 使用 flash 属性
    • 7.6 小结
  • 第 8 章 使用 Spring Web Flow
    • 8.1 在 Spring 中配置 Web Flow
      • 8.1.1 装配流程执行器
      • 8.1.2 配置流程注册表
      • 8.1.3 处理流程请求
    • 8.2 流程的组件
      • 8.2.1 状态
      • 8.2.2 转移
      • 8.2.3 流程数据
    • 8.3 组合起来:披萨流程
      • 8.3.1 定义基本流程
      • 8.3.2 收集顾客信息
      • 8.3.3 构建订单
      • 8.3.4 支付
    • 8.4 保护 Web 流程
    • 8.5 小结
  • 第 9 章 保护 Web 应用
    • 9.1 Spring Security 简介
      • 9.1.1 理解 Spring Security 的模块
      • 9.1.2 过滤 Web 请求
      • 9.1.3 编写简单的安全性配置
    • 9.2 选择查询用户详细信息的服务
      • 9.2.1 使用基于内存的用户存储
      • 9.2.2 基于数据库表进行认证
      • 9.2.3 基于 LDAP 进行认证
      • 9.2.4 配置自定义的用户服务
    • 9.3 拦截请求
      • 9.3.1 使用 Spring 表达式进行安全保护
      • 9.3.2 强制通道的安全性
      • 9.3.3 防止跨站请求伪造
    • 9.4 认证用户
      • 9.4.1 添加自定义的登录页
      • 9.4.2 启用 HTTP Basic 认证
      • 9.4.3 启用 Remember-me 功能
      • 9.4.4 退出
    • 9.5 保护视图
      • 9.5.1 使用 Spring Security 的 JSP 标签库
      • 9.5.2 使用 Thymeleaf 的 Spring Security 方言
    • 9.6 小结
  • 第三部分 后端中的 Spring
  • 第 10 章 通过 Spring 和 JDBC 征服数据库
    • 10.1 Spring 的数据访问哲学
      • 10.1.1 了解 Spring 的数据访问异常体系
      • 10.1.2 数据访问模板化
    • 10.2 配置数据源
      • 10.2.1 使用 JNDI 数据源
      • 10.2.2 使用数据源连接池
      • 10.2.3 基于 JDBC 驱动的数据源
      • 10.2.4 使用嵌入式的数据源
      • 10.2.5 使用 profile 选择数据源
    • 10.3 在 Spring 中使用 JDBC
      • 10.3.1 应对失控的 JDBC 代码
      • 10.3.2 使用 JDBC 模板
    • 10.4 小结
  • 第 11 章 使用对象-关系映射持久化数据
    • 11.1 在 Spring 中集成 Hibernate
      • 11.1.1 声明 Hibernate 的 Session 工厂
      • 11.1.2 构建不依赖于 Spring 的 Hibernate 代码
    • 11.2 Spring 与 Java 持久化 API
      • 11.2.1 配置实体管理器工厂
      • 11.2.2 编写基于 JPA 的 Repository
    • 11.3 借助 Spring Data 实现自动化的 JPARepository
      • 11.3.1 定义查询方法
      • 11.3.2 声明自定义查询
      • 11.3.3 混合自定义的功能
    • 11.4 小结
  • 第 12 章 使用 NoSQL 数据库
    • 12.1 使用 MongoDB 持久化文档数据
      • 12.1.1 启用 MongoDB
      • 12.1.2 为模型添加注解,实现 MongoDB 持久化
      • 12.1.3 使用 MongoTemplate 访问 MongoDB
      • 12.1.4 编写 MongoDB Repository
    • 12.2 使用 Neo4j 操作图数据
      • 12.2.1 配置 Spring Data Neo4j
      • 12.2.2 使用注解标注图实体
      • 12.2.3 使用 Neo4jTemplate
      • 12.2.4 创建自动化的 Neo4j Repository
    • 12.3 使用 Redis 操作 key-value 数据
      • 12.3.1 连接到 Redis
      • 12.3.2 使用 Redis Template
      • 12.3.3 使用 key 和 value 的序列化器
    • 12.4 小结
  • 第 13 章 缓存数据
    • 13.1 启用对缓存的支持
      • 13.1.1 配置缓存管理器
    • 13.2 为方法添加注解以支持缓存
      • 13.2.1 填充缓存
      • 13.2.2 移除缓存条目
    • 13.3 使用 XML 声明缓存
    • 13.4 小结
  • 第 14 章 保护方法应用
    • 14.1 使用注解保护方法
      • 14.1.1 使用 @Secured 注解限制方法调用
      • 14.1.2 在 Spring Security 中使用 JSR-250 的 @RolesAllowed 注解
    • 14.2 使用表达式实现方法级别的安全性
      • 14.2.1 表述方法访问规则
      • 14.2.2 过滤方法的输入和输出
    • 14.3 小结
  • 第四部分 Spring 集成
  • 第 15 章 使用远程服务
    • 15.1 Spring 远程调用概览
    • 15.2 使用 RMI
      • 15.2.1 导出 RMI 服务
      • 15.2.2 装配 RMI 服务
    • 15.3 使用 Hessian 和 Burlap 发布远程服务
      • 15.3.1 使用 Hessian 和 Burlap 导出 bean 的功能
      • 15.3.2 访问 Hessian/Burlap 服务
    • 15.4 使用 Spring 的 HttpInvoker
      • 15.4.1 将 bean 导出为 HTTP 服务
      • 15.4.2 通过 HTTP 访问服务
    • 15.5 发布和使用 Web 服务
      • 15.5.1 创建基于 Spring 的 JAX-WS 端点
      • 15.5.2 在客户端代理 JAX-WS 服务
    • 15.6 小结
  • 第 16 章 使用 Spring MVC 创建 REST API
    • 16.1 了解 REST
      • 16.1.1 REST 的基础知识
      • 16.1.2 Spring 是如何支持 REST 的
    • 16.2 创建第一个 REST 端点
      • 16.2.1 协商资源表述
      • 16.2.2 使用 HTTP 信息转换器
    • 16.3 提供资源之外的其他内容
      • 16.3.1 发送错误信息到客户端
      • 16.3.2 在响应中设置头部信息
    • 16.4 编写 REST 客户端
      • 16.4.1 了解 RestTemplate 的操作
      • 16.4.2 GET 资源
      • 16.4.3 检索资源
      • 16.4.4 抽取响应的元数据
      • 16.4.5 PUT 资源
      • 16.4.6 DELETE 资源
      • 16.4.7 POST 资源数据
      • 16.4.8 在 POST 请求中获取响应对象
      • 16.4.9 在 POST 请求后获取资源位置
      • 16.4.10 交换资源
    • 16.5 小结
  • 第 17 章 Spring 消息
    • 17.1 异步消息简介
      • 17.1.1 发送消息
      • 17.1.2 评估异步消息的优点
    • 17.2 使用 JMS 发送消息
      • 17.2.1 在 Spring 中搭建消息代理
      • 17.2.2 使用 Spring 的 JMS 模板
      • 17.2.3 创建消息驱动的 POJO
      • 17.2.4 使用基于消息的 RPC
    • 17.3 使用 AMQP 实现消息功能
      • 17.3.1 AMQP 简介
      • 17.3.2 配置 Spring 支持 AMQP 消息
      • 17.3.3 使用 RabbitTemplate 发送消息
      • 17.3.4 接收 AMQP 消息
    • 17.4 小结
  • 第 18 章 使用 WebSocket 和 STOMP 实现消息功能
    • 18.1 使用 Spring 的低层级 WebSocket API
    • 18.2 应对不支持 WebSocket 的场景
    • 18.3 使用 STOMP 消息
      • 18.3.1 启用 STOMP 消息功能
      • 18.3.2 处理来自客户端的 STOMP 消息
      • 18.3.3 发送消息到客户端
    • 18.4 为目标用户发送消息
      • 18.4.1 在控制器中处理用户的消息
      • 18.4.2 为指定用户发送消息
    • 18.5 处理消息异常
    • 18.6 小结
  • 第 19 章 使用 Spring 发送 Email
    • 19.1 配置 Spring 发送邮件
      • 19.1.1 配置邮件发送器
      • 19.1.2 装配和使用邮件发送器
    • 19.2 构建丰富内容的 Email 消息
      • 19.2.1 添加附件
      • 19.2.2 发送富文本内容的 Email
    • 19.3 使用模板生成 Email
      • 19.3.1 使用 Velocity 构建 Email 消息
      • 19.3.2 使用 Thymeleaf 构建 Email 消息
    • 19.4 小结
  • 第 20 章 使用 JMX 管理 SpringBean
    • 20.1 将 Spring bean 导出为 MBean
      • 20.1.1 通过名称暴露方法
      • 20.1.2 使用接口定义 MBean 的操作和属性
      • 20.1.3 使用注解驱动的 MBean
      • 20.1.4 处理 MBean 冲突
    • 20.2 远程 MBean
      • 20.2.1 暴露远程 MBean
      • 20.2.2 访问远程 MBean
      • 20.2.3 代理 MBean
    • 20.3 处理通知
      • 20.3.1 监听通知
    • 20.4 小结
  • 第 21 章 借助 Spring Boot 简化 Spring 开发
    • 21.1 Spring Boot 简介
      • 21.1.1 添加 Starter 依赖
      • 21.1.2 自动配置
      • 21.1.3 Spring Boot CLI
      • 21.1.4 Actuator
    • 21.2 使用 Spring Boot 构建应用
      • 21.2.1 处理请求
      • 21.2.2 创建视图
      • 21.2.3 添加静态内容
      • 21.2.4 持久化数据
      • 21.2.5 尝试运行
    • 21.3 组合使用 Groovy 与 Spring Boot CLI
      • 21.3.1 编写 Groovy 控制器
      • 21.3.2 使用 Groovy Repository 实现数据持久化
      • 21.3.3 运行 Spring Boot CLI
    • 21.4 通过 Actuator 获取了解应用内部状况
    • 21.5 小结
Powered by GitBook
On this page

Was this helpful?

  1. 第 10 章 通过 Spring 和 JDBC 征服数据库
  2. 10.3 在 Spring 中使用 JDBC

10.3.2 使用 JDBC 模板

Spring 的 JDBC 框架承担了资源管理和异常处理的工作,从而简化了 JDBC 代码,让我们只需编写从数据库读写数据的必需代码。

正如前面小节所介绍过的,Spring 将数据访问的样板代码抽象到模板类之中。Spring 为 JDBC 提供了三个模板类供选择:

  • JdbcTemplate:最基本的 Spring JDBC 模板,这个模板支持简单的 JDBC 数据库访问功能以及基于索引参数的查询;

  • NamedParameterJdbcTemplate:使用该模板类执行查询时可以将值以命名参数的形式绑定到 SQL 中,而不是使用简单的索引参数;

  • SimpleJdbcTemplate:该模板类利用 Java 5 的一些特性如自动装箱、泛型以及可变参数列表来简化 JDBC 模板的使用。

以前,在选择哪一个 JDBC 模板的时候,我们需要仔细权衡。但是从 Spring 3.1 开始,做这个决定变得容易多了。SimpleJdbcTemplate 已经被废弃了,其 Java 5 的特性被转移到了 JdbcTemplate 中,并且只有在你需要使用命名参数的时候,才需要使 用 NamedParameterJdbcTemplate。这样的话,对于大多数的 JDBC 任务来说,JdbcTemplate 就是最好的可选方案,这也是本小节中所关注的方案。

使用 JdbcTemplate 来插入数据

为了让 JdbcTemplate 正常工作,只需要为其设置 DataSource 就可以了,这使得在 Spring 中配置 JdbcTemplate 非常容易,如下面的 @Bean 方法所示:

@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
  return new JdbcTemplate(dataSource);
}

在这里,DataSource 是通过构造器参数注入进来的。这里所引用的 dataSource bean 可以是 javax.sql.DataSource 的任意实现,包括我们在 10.2 小节中所创建的。

现在,我们可以将 jdbcTemplate 装配到 Repository 中并使用它来访问数据库。例如,SpitterRepository 使用了 JdbcTemplate:

public class JdbcSpitterRepository implements SpitterRepository {
	
	private JdbcOperations jdbcOperations;

	public JdbcSpitterRepository(JdbcOperations jdbcOperations) {
		this.jdbcOperations= jdbcOperations;		
	}
	
	...
}

在这里,JdbcSpitterRepository 类上使用了 @Repository 注解,这表明它将会在组件扫描的时候自动创建。它的构造器上使用了 @Inject 注解,因此在创建的时候,会自动获得一个 JdbcOperations 对象。JdbcOperations 是一个接口,定义了 JdbcTemplate 所实现的操作。通过注入 JdbcOperations,而不是具体的 JdbcTemplate,能够保证 JdbcSpitterRepository 通过 JdbcOperations 接口达到与 JdbcTemplate 保持松耦合。

作为另外一种组件扫描和自动装配的方案,我们可以将 JdbcSpitterRepository 显式声明为 Spring 中的 bean,如下所示:

@Bean
public SpitterRepository spitterRepository(JdbcTemplate jdbcTemplate) {
  return new jdbcSpitterRepository(jdbcTemplate);
}

在 Repository 中具备可用的 JdbcTemplate 后,我们可以极大地简化程序清单 10.4 中的 addSpitter() 方法。基于 JdbcTemplate 的 addSpitter() 方法如下:

程序清单 10.7 基于 JdbcTemplate 的 addSpitter() 方法
private void insertSpitter(Spitter spitter) {
  jdbcTemplate.update(INSERT_SPITTER,
    spitter.getUsername(),
    spitter.getPassword(),
    spitter.getFullName(),
    spitter.getEmail(),
    spitter.isUpdateByEmail());
}

这个版本的 addSpitter() 方法简单多了。这里没有了创建连接和语句的代码,也没有异常处理的代码,只剩下单纯的数据插入代码。

不能因为你看不到这些样板代码,就意味着它们不存在。样板代码被巧妙地隐藏到 JDBC 模板类中了。当 update() 方法被调用的时候 JdbcTemplate 将会获取连接、创建语句并执行插入 SQL。

在这里,你也看不到对 SQLException 处理的代码。在内部,JdbcTemplate 将会捕获所有可能抛出的 SQLException,并将通用的 SQLException 转换为表 10.1 所列的那些更明确的数据访问异常,然后将其重新抛出。因为 Spring 的数据访问异常都是运行时异常,所以我们不必在 addSpitter() 方法中进行捕获。

使用 JdbcTemplate 来读取数据

JdbcTemplate 也简化了数据的读取操作。程序清单 10.8 展现了新版本的 findOne() 方法,它使用了 JdbcTemplate 的回调,实现根据 ID 查询 Spitter,并将结果集映射为 Spitter 对象。

程序清单 10.8 使用 JdbcTemplate 查询 Spitter
public Spitter findOne(long id) {
  return jdbcTemplate.queryForObject(
    SELECT_SPITTER + " where id=?", new SpitterRowMapper(), id);
}

...

private static final class SpitterRowMapper implements RowMapper<Spitter> {
  public Spitter mapRow(ResultSet rs, int rowNum) throws SQLException {
	return new Spitter(
	  rs.getLong("id"),
	  rs.getString("username"),
	  rs.getString("password"),
	  rs.getString("fullname"),
	  rs.getString("email"),
	  rs.getBoolean("updateByEmail"));
  }		
}

在这个 findOne() 方法中使用了 JdbcTemplate 的 queryForObject() 方法来从数据库查询 Spitter。queryForObject() 方法有三个参数:

  • String 对象,包含了要从数据库中查找数据的 SQL;

  • RowMapper 对象,用来从 ResultSet 中提取数据并构建域对象(本例中为 Spitter);

  • 可变参数列表,列出了要绑定到查询上的索引参数值。

真正奇妙的事情发生在 SpitterRowMapper 对象中,它实现了 RowMapper 接口。对于查询返回的每一行数据,JdbcTemplate 将会调用 RowMapper 的 mapRow() 方法,并传入一个 ResultSet 和包含行号的整数。在 SpitterRowMapper 的 mapRow() 方法中,我们创建了 Spitter 对象并将 ResultSet 中的值填充进去。

就像 addSpitter() 那样,findOne() 方法也不用写 JDBC 模板代 码。不同于传统的 JDBC,这里没有资源管理或者异常处理代码。使用 JdbcTemplate 的方法只需关注于如何从数据库中获取 Spitter 对象即可。

在 JdbcTemplate 中使用 Java 8 的 Lambda 表达式

因为 RowMapper 接口只声明了 addRow() 这一个方法,因此它完全 符合函数式接口(functional interface)的标准。这意味着如果使用 Java 8 来开发应用的话,我们可以使用 Lambda 来表达 RowMapper 的实现,而不必再使用具体的实现类了。

例如,程序清单 10.8 中的 findOne() 方法可以使用 Java 8 的 Lambda 表达式改写,如下所示:

程序清单 10.8 使用 JdbcTemplate 查询 Spitter
public Spitter findOne(long id) {
	return jdbcOperations.queryForObject(
	  SELECT_SPITTER_BY_ID,
	  (rs, rowNum) -> {
	    return new Spitter(
	      rs.getLong("id"),
	      rs.getString("username"),
    	  rs.getString("password"),
	      rs.getString("fullname"),
	      rs.getString("email"),
	      rs.getBoolean("updateByEmail"));
	},
	id);
}

我们可以看到,Lambda 表达式要比完整的 RowMapper 实现更为易读,不过它们的功能是相同的。Java 会限制 RowMapper 中的 Lambda 表达式,使其满足所传入的参数。

另外,我们还可以使用 Java 8 的方法引用,在单独的方法中定义映射逻辑:

public Spitter findOne(long id) {
  return jdbcOperations.queryForObejct(
    SELECT_SPITTER_BY_ID, this::mapSpitter, id);
}

private Spitter mapSpitter(ResultSet rs, int row) throws Exception {
  return new Spitter(
    rs.getLong("id"),
	rs.getString("username"),
    rs.getString("password"),
	rs.getString("fullname"),
	rs.getString("email"),
	rs.getBoolean("updateByEmail"));
}

不管采用哪种方式,我们都不必显式实现 RowMapper 接口,但是与实现 RowMapper 类似,我们所提供的 Lambda 表达式和方法必须要接受相同的参数,并返回相同的类型。

使用命名参数

在清单 10.7 的代码中,addSpitter() 方法使用了索引参数。这意味着我们需要留意查询中参数的顺序,在将值传递给 update() 方法的时候要保持正确的顺序。如果在修改 SQL 时更改了参数的顺序,那我们还需要修改参数值的顺序。

除了这种方法之外,我们还可以使用命名参数。命名参数可以赋予 SQL 中的每个参数一个明确的名字,在绑定值到查询语句的时候就通过该名字来引用参数。例如,假设 SQL_INSERT_SPITTER 查询语句是这样定义的:

private static final Spitter SQL_INSERT_SPITTER = 
  "insert into spitter (username, password, fullname) " +
  "values (:username, :password, :fullname)";

使用命名参数查询,绑定值的顺序就不重要了,我们可以按照名字来绑定值。如果查询语句发生了变化导致参数的顺序与之前不一致,我们不需要修改绑定的代码。

NamedParameterJdbcTemplate 是一个特殊的 JDBC 模板类,它支持使用命名参数。在 Spring 中,NamedParameterJdbcTemplate 的声明方式与常规的 JdbcTemplate 几乎完全相同:

@Bean
public NamedParameterJdbcTemplate jdbcTemplate(DataSource dataSource) {
  return new NamedParameterJdbcTemplate(dataSource);
}

在这里,我们将NamedParameterJdbcOperations(NamedParameter-JdbcTemplate 所实现的接口)注入到 Repository 中,用它来替代 JdbcOperations。现在的 addSpitter() 方法如下所示:

程序清单 10.9 使用 Spring JDBC 模板的命名参数功能
private static final String INSERT_SPITTER =
  "insert into Spitter " +
  "  (username, password, fullname, email, updateByEmail) " +
  "values " +
  "  (:username, :password, :fullname, :email, :updateByEmail)";

private void addSpitter(Spitter spitter) {
  Map<String, Object> paramMap = new HashMap<String, Object>();
  paramMap.put("username", spitter.getUsername());
  paramMap.put("password", spitter.getPassword());
  paramMap.put("fullname", spitter.getFullName());
  paramMap.put("email", spitter.getEmail());
  paramMap.put("updateByEmail", spitter.isUpdateByEmail());
  jdbcOperations.update(INSERT_SPITTER, paramMap);
}

这个版本的 addSpitter() 比前一版本的代码要长一些。这是因为命名参数是通过 java.util.Map 来进行绑定的。不过,每行代码都关注于往数据库中插入 Spitter 对象。这个方法的核心功能并不会被资源管理或异常处理这样的代码所充斥。

Previous10.3.1 应对失控的 JDBC 代码Next10.4 小结

Last updated 5 years ago

Was this helpful?