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. 第 11 章 使用对象-关系映射持久化数据
  2. 11.2 Spring 与 Java 持久化 API

11.2.1 配置实体管理器工厂

简单来讲,基于 JPA 的应用程序需要使用 EntityManagerFactory 的实现类来获取 EntityManager 实例。JPA 定义了两种类型的实体管理器:

  • 应用程序管理类型(Application-managed):当应用程序向实体管理器工厂直接请求实体管理器时,工厂会创建一个实体管理器。在这种模式下,程序要负责打开或关闭实体管理器并在事务中对其进行控制。这种方式的实体管理器适合于不运行在 Java EE 容器中的独立应用程序。

  • 容器管理类型(Container-managed):实体管理器由 Java EE 创建和管理。应用程序根本不与实体管理器工厂打交道。相反,实体管理器直接通过注入或 JNDI 来获取。容器负责配置实体管理器工厂。这种类型的实体管理器最适用于 Java EE 容器,在这种情况下会希望在 persistence.xml 指定的 JPA 配置之外保持一些自己对 JPA 的控制。

以上的两种实体管理器实现了同一个 EntityManager 接口。关键的区别不在于 EntityManager 本身,而是在于 EntityManager 的创建和管理方式。应用程序管理类型的 EntityManager 是由 EntityManagerFactory 创建的,而后者是通过 PersistenceProvider 的 createEntityManagerFactory() 方法得到的。与此相对,容器管理类型的 EntityManagerFactory 是通过 PersistenceProvider 的 createContainerEntityManagerFactory() 方法获得的。

这对想使用 JPA 的 Spring 开发者来说又意味着什么呢?其实这并没太大的关系。不管你希望使用哪种 EntityManagerFactory,Spring 都会负责管理 EntityManager。如果你使用的是应用程序管理类型的实体管理器,Spring 承担了应用程序的角色并以透明的方式处理 EntityManager。在容器管理的场景下,Spring 会担当容器的角色。

这两种实体管理器工厂分别由对应的 Spring 工厂 Bean 创建:

  • LocalEntityManagerFactoryBean 生成应用程序管理类型的 EntityManagerFactory;

  • LocalContainerEntityManagerFactoryBean 生成容器管理类型的 EntityManagerFactory。

需要说明的是,选择应用程序管理类型的还是容器管理类型的 EntityManager-Factory,对于基于 Spring 的应用程序来讲是完全透明的。当组合使用 Spring 和 JPA 时,处理 EntityManagerFactory 的复杂细节被隐藏了起来,数据访问代码只需关注它们的真正目标即可,也就是数据访问。

应用程序管理类型和容器管理类型的实体管理器工厂之间唯一值得关注的区别是在 Spring 应用上下文中如何进行配置。让我们先看看如何在 Spring 中配置应用程序管理类型的 LocalEntityManagerFactoryBean,然后再看看如何配置容器管理类型的 LocalContainerEntityManagerFactoryBean。

配置应用程序管理类型的 JPA

对于应用程序管理类型的实体管理器工厂来说,它绝大部分配置信息来源于一个名为 persistence.xml 的配置文件。这个文件必须位于类路径下的 META-INF 目录下。

persistence.xml 的作用在于定义一个或多个持久化单元。持久化单元是同一个数据源下的一个或多个持久化类。简单来讲,persistence.xml 列出了一个或多个的持久化类以及一些其他的配置如数据源和基于 XML 的配置文件。如下是一个典型的 persistence.xml 文件,它是用于 Spittr 应用程序的:

<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence">
  <persistence-unit name="spitterPU">
    <class>com.habuma.spittr.domain.Spitter</class>
    <class>com.habuma.spittr.domain.Spittle</class>
    <properties>
      <property name="toplink.jdbc.driver" value="org.hsqldb.jdbcDriver" />
      <property name="toplink.jdbc.url" value="jdbc:hsqldb:hsql://localhost/spitter/spitter" />
      <property name="toplink.jdbc.user" value="sa" />
      <property name="toplink.jdbc.password" value="" />
    </properties>
  </persistence-unit>
</persistence>

因为在 persistence.xml 文件中包含了大量的配置信息,所以在 Spring 中需要配置的就很少了。可以通过以下的 @Bean 注解方法在 Spring 中声明 LocalEntityManagerFactoryBean:

@Bean
public LocalEntityManagerFactoryBean entityManagerFactoryBean() {
  LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
  emfb.setPersistenceUnitName("spitterPU");
  return emfb;
}

赋给 persistenceUnitName 属性的值就是 persistence.xml 中持久化单元的名称。

创建应用程序管理类型的 EntityManagerFactory 都是在 persistence.xml 中进行的,而这正是应用程序管理的本意。在应用程序管理的场景下(不考虑 Spring 时),完全由应用程序本身来负责获取 EntityManagerFactory,这是通过 JPA 实现的 PersistenceProvider 做到的。如果每次请求 EntityManagerFactory 时都需要定义持久化单元,那代码将会迅速膨胀。通过将其配置在 persistence.xml 中,JPA 就能够在这个特定的位置查找持久化单元定义了。

但借助于 Spring 对 JPA 的支持,我们不再需要直接处理 PersistenceProvider 了。因此,再将配置信息放在 persistence.xml 中就显得不那么明智了。实际上,这样做妨碍了我们在 Spring 中配置 EntityManagerFactory(如果不是这样的话,我们可以提供一个 Spring 配置的数据源)。

鉴于以上的原因,让我们关注一下容器管理的 JPA:

使用容器管理类型的 JPA

容器管理的 JPA 采取了一个不同的方式。当运行在容器中时,可以使用容器(在我们的场景下是 Spring)提供的信息来生成 EntityManagerFactory。

你可以将数据源信息配置在 Spring 应用上下文中,而不是在 persistence.xml 中了。例如,如下的 @Bean 注解方法声明了在 Spring 中如何使用 LocalContainer-EntityManagerFactoryBean 来配置容器管理类型的 JPA:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
    DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
  LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
  emfb.setDataSource(dataSource);
  emfb.setJpaVendorAdapter(jpaVendorAdapter);
  return emfb;
}

这里,我们使用了 Spring 配置的数据源来设置 dataSource 属性。任何 javax.sql.DataSource 的实现都是可以的。尽管数据源还可以在 persistence.xml 中进行配置,但是这个属性指定的数据源具有更高的优先级。

jpaVendorAdapter 属性用于指明所使用的是哪一个厂商的 JPA 实现。Spring 提供了多个 JPA 厂商适配器:

  • EclipseLinkJpaVendorAdapter

  • HibernateJpaVendorAdapter

  • OpenJpaVendorAdapter

  • TopLinkJpaVendorAdapter(在Spring 3.1版本中,已经将其废弃了)

在本例中,我们使用 Hibernate 作为 JPA 实现,所以将其配置为 Hibernate-JpaVendorAdapter:

@Bean
public JpaVendorAdapter jpaVendorAdapter() {
  HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
  adapter.setDatabase("HSQL");
  adapter.setShowSql(true);
  adapter.setGenerateDdl(false);
  adapter.setDatabasePlatform("org.hibernet.dialect.HSQLDialect");
  return adapter;
}

有多个属性需要设置到厂商适配器上,但是最重要的是 database 属性,在上面我们设置了要使用的数据库是 Hypersonic。这个属性支持的其他值如表 11.1 所示。

数据库平台

属性 database 的值

IBM DB2

DB2

Apache Derby

DERBY

H2

H2

Hypersonic

HSQL

Informix

INFORMIX

MySQL

MYSQL

Oracle

ORACLE

PostgresQL

POSTGRESQL

Microsoft SQL Server

SQLSERVER

Sybase

SYBASE

一些特定的动态持久化功能需要对持久化类按照指令(instrumentation)进行修改才能支持。在属性延迟加载(只在它们被实际访问时才从数据库中获取)的对象中,必须要包含知道如何查询未加载数据的代码。一些框架使用动态代理实现延迟加载,而有一些框架像 JDO,则是在编译时执行类指令。

选择哪一种实体管理器工厂主要取决于如何使用它。但是,下面的小技巧可能会让你更加倾向于使用 LocalContainerEntityManagerFactoryBean。

persistence.xml 文件的主要作用就在于识别持久化单元中的实体类。但是从 Spring 3.1 开始,我们能够在 LocalContainerEntityManagerFactoryBean 中直接设置 packagesToScan 属性:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
    DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
  LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
  emfb.setDataSource(dataSource);
  emfb.setJpaVendorAdapter(jpaVendorAdapter);
  emfb.setPackagesToScan("com.habuma.spittr.domain");
  return emfb;
}

在这个配置中,LocalContainerEntityManagerFactoryBean 会扫描 com.habuma .spittr.domain 包,查找带有 @Entity 注解的类。因此,没有必要在 persistence.xml 文件中进行声明了。同时,因为 DataSource 也是注入到 LocalContainerEntity-ManagerFactoryBean 中的,所以也没有必要在 persistence.xml 文件中配置数据库信息了。那么结论就是,persistence.xml 文件完全没有必要存在了!你尽可以将其删除,让 LocalContainerEntityManagerFactoryBean 来处理这些事情。

从 JNDI 获取实体管理器工厂

还有一件需要注意的事项,如果将 Spring 应用程序部署在应用服务器中,EntityManagerFactory 可能已经创建好了并且位于 JNDI 中等待查询使用。在这种情况下,可以使用 Spring jee 命名空间下的 <jee:jndi-lookup> 元素来获取对 EntityManagerFactory 的引用:

<jee:jndi-lookup id="emf" jndi-name="persistence/spitterPU" />

我们也可以使用如下的 Java 配置来获取 EntityManagerFactory:

@Bean
public JndiObjectFactoryBean entityManagerFactory() {
  JndiObjectFactoryBean jndiObjectFB = new JndiObjectFactoryBean();
  jndiObjectFB.setJndiName("jdbc/SpittrDS");
  return jndiObjectFB;
}

尽管这种方法没有返回 EntityManagerFactory,但是它的结果就是一个 EntityManagerFactoryBean。这是因为它所返回的 JndiObjectFactoryBean 是 FactoryBean 接口的实现,它能够创建 EntityManagerFactory。

不管你采用何种方式得到 EntityManagerFactory,一旦得到这样的对象,接下来就可以编写 Repository 了。让我们开始吧。

Previous11.2 Spring 与 Java 持久化 APINext11.2.2 编写基于 JPA 的 Repository

Last updated 5 years ago

Was this helpful?