《Spring 5 官方文档》16.ORM和数据访问(三)

16.4.2 基于JPA的EntityManagerFactory和EntityManager来实现DAO

虽然EntityManagerFactory实例是线程安全的,但EntityManager实例不是。注入的JPA EntityManager的行为类似于从JPA Spec中定义的应用程序服务器的JNDI环境中提取的EntityManager。它将所有调用委托给当前事务的EntityManager(如果有);否则,它每个操作返回的都是新创建的EntityManager,通过使用不同的EntityManager来保证使用时的线程安全。

通过注入的方式使用EntityManagerFactoryEntityManager来编写JPA代码,是不需要依赖任何Spring定义的类的。如果启用了PersistenceAnnotationBeanPostProcessor,Spring可以在实例级别和方法级别识别@PersistenceUnit@PersistenceContext注解。使用@PersistenceUnit注解的纯JPA DAO实现可能如下所示:

  1. public class ProductDaoImpl implements ProductDao {
  2. private EntityManagerFactory emf;
  3. @PersistenceUnit
  4. public void setEntityManagerFactory(EntityManagerFactory emf) {
  5. this.emf = emf;
  6. }
  7. public Collection loadProductsByCategory(String category) {
  8. EntityManager em = this.emf.createEntityManager();
  9. try {
  10. Query query = em.createQuery("from Product as p where p.category = ?1");
  11. query.setParameter(1, category);
  12. return query.getResultList();
  13. }
  14. finally {
  15. if (em != null) {
  16. em.close();
  17. }
  18. }
  19. }
  20. }

上面的DAO对Spring的实现是没有任何依赖的,而且很适合与Spring的应用程序上下文进行集成。而且,DAO还可以通过注解来注入默认的EntityManagerFactory

  1. <beans>
  2. <!-- bean post-processor for JPA annotations -->
  3. <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
  4. <bean id="myProductDao" class="product.ProductDaoImpl"/>
  5. </beans>

如果不想明确定义PersistenceAnnotationBeanPostProcessor,可以考虑在应用程序上下文配置中使用Spring上下文annotation-configXML元素。这样做会自动注册所有Spring标准后置处理器,用于初始化基于注解的配置,包括CommonAnnotationBeanPostProcessor等。

  1. <beans>
  2. <!-- post-processors for all standard config annotations -->
  3. <context:annotation-config/>
  4. <bean id="myProductDao" class="product.ProductDaoImpl"/>
  5. </beans>

这样的DAO的主要问题是它总是通过工厂创建一个新的EntityManager。开发者可以通过请求事务性EntityManager(也称为共享EntityManager,因为它是实际的事务性EntityManager的一个共享的,线程安全的代理)来避免这种情况。

  1. public class ProductDaoImpl implements ProductDao {
  2. @PersistenceContext
  3. private EntityManager em;
  4. public Collection loadProductsByCategory(String category) {
  5. Query query = em.createQuery("from Product as p where p.category = :category");
  6. query.setParameter("category", category);
  7. return query.getResultList();
  8. }
  9. }

@PersistenceContext注解具有可选的属性类型,默认值为PersistenceContextType.TRANSACTION。此默认值是开发者所需要接收共享的EntityManager代理。替代方案PersistenceContextType.EXTENDED则完全不同:该方案会返回一个所谓扩展的EntityManager,该EntityManager不是线程安全的,因此不能在并发访问的组件(如Spring管理的单例Bean)中使用。扩展实体管理器仅应用于状态组件中,比如持有会话的组件,其中EntityManager的生命周期与当前事务无关,而是完全取决于应用程序。

方法和实例变量级别注入

指示依赖注入(例如@PersistenceUnit@PersistenceContext)的注解可以应用于类中的实例变量或方法,也就是表达式方法级注入和实例变量级注入。实例变量级注释简洁易用,而方法级别允许进一步处理注入的依赖关系。在这两种情况下,成员的可见性(publicprotectedprivate)并不重要。

类级注解怎么办?

在J2EE平台上,它们用于依赖关系声明,而不是资源注入。

注入的EntityManager是由Spring管理的(Spring可以意识到正在进行的事务)。重要的是要注意,因为通过注解进行注入,即使新的DAO实现使用通过方法注入的EntityManager而不是EntityManagerFactory的注入的,在应用程序上下文XML中不需要进行任何修改。

这种DAO风格的主要优点是它只依赖于Java Persistence API;不需要导入任何Spring的实现类。而且,Spring容器可以识别JPA注解来实现自动的注入和管理。从非侵入的角度来看,这种风格对JPA开发者来说可能更为自然。

16.4.3 Spring驱动的JPA事务

如果开发者还没有阅读声明式事务管理,强烈建议开发者先行阅读,这样可以更详细地了解Spring的对声明式事务支持。

JPA的推荐策略是通过JPA的本地事务支持的本地事务。 Spring的JpaTransactionManager提供了许多来自本地JDBC事务的功能,例如针对任何常规JDBC连接池(不需要XA要求)指定事务的隔离级别和资源级只读优化等。

Spring JPA还允许配置JpaTransactionManager将JPA事务暴露给访问同一DataSource的JDBC访问代码,前提是注册的JpaDialect支持检索底层JDBC连接。Spring为EclipseLink和Hibernate JPA实现提供了实现。有关JpaDialect机制的详细信息,请参阅下一节。

16.4.4 JpaDialect和JpaVendorAdapter

作为高级功能,JpaTransactionManagerAbstractEntityManagerFactoryBean的子类支持自定义JpaDialect,将其作为Bean传递给jpaDialect属性。JpaDialect实现可以以供应商特定的方式使能Spring支持的一些高级功能:

  • 应用特定的事务语义,如自定义隔离级别或事务超时
  • 为基于JDBC的DAO导出事务性JDBC连接
  • PersistenceExceptions到SpringDataAccessExceptions的异常转义

这对于特殊的事务语义和异常的高级翻译特别有价值。但是Spring使用的默认实现(DefaultJpaDialect)是不提供任何特殊功能的。如果需要上述功能,则必须指定适当的方言才可以。

作为一个更广泛的供应商适应设施,主要用于Spring的全功能LocalContainerEntityManagerFactoryBean设置,JpaVendorAdapterJpaDialect的功能与其他提供者特定的默认设置相结合。指定HibernateJpaVendorAdapterEclipseLinkJpaVendorAdapter是分别为Hibernate或EclipseLink自动配置EntityManagerFactory设置的最简单方便的方法。但是请注意,这些提供程序适配器主要是为了与Spring驱动的事务管理一起使用而设计的,即为了与JpaTransactionManager配合使用的。

有关其操作的更多详细信息以及在Spring的JPA支持中如何使用,请参阅JpaDialectJpaVendorAdapter的Javadoc。

16.4.5 为JPA配置JTA事务管理

作为JpaTransactionManager的替代方案,Spring还允许通过JTA在J2EE环境中或与独立的事务协调器(如Atomikos)进行多资源事务协调。除了用Spring的JtaTransactionManager替换JpaTransactionManager,还有需要以下一些操作:

  • 底层JDBC连接池是需要具备XA功能,并与开发者的事务协调器集成的。这在J2EE环境中很简单,只需通过JNDI导出不同类型的DataSource即可。有关导出DataSource等详细信息,可以参考应用服务器文档。类似地,独立的事务协调器通常带有特殊的XA集成的DataSource实现。
  • 需要为JTA配置JPAEntityManagerFactory。这是特定于提供程序的,通常通过在LocalContainerEntityManagerFactoryBean的特殊属性指定为”jpaProperties”。在使用Hibernate的情况下,这些属性甚至是需要基于特定的版本的;请查阅Hibernate文档以获取详细信息。
  • Spring的HibernateJpaVendorAdapter会强制执行某些面向Spring的默认设置,例如在Hibernate 5.0中匹配Hibernate自己的默认值的连接释放模式“on-close”,但在5.1 / 5.2中不再存在。对于JTA设置,不要声明HibernateJpaVendorAdapter开始,或关闭其prepareConnection标志。或者,将Hibernate 5.2的hibernate.connection.handling_mode属性设置为DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT以恢复Hibernate自己的默认值。有关WebLogic的相关说明,请参考Hibernate的虚假应用服务器警告一节。
  • 或者,可以考虑从应用程序服务器本身获取EntityManagerFactory,即通过JNDI查找而不是本地声明的LocalContainerEntityManagerFactoryBean。服务器提供的EntityManagerFactory可能需要在服务器配置中进行特殊定义,减少了部署的移植性,但是EntityManagerFactory将为开箱即用的服务器JTA环境设置。

转载自 并发编程网 - ifeve.com  

时间: 2025-01-01 06:07:01

《Spring 5 官方文档》16.ORM和数据访问(三)的相关文章

《Spring 5 官方文档》26. JMS(三)

26.6 注解驱动的监听端点 异步接收消息的最简单的方法是使用注解监听端点的基础架构.简而言之,它允许你暴露托管一个 bean 的方法作为一个 JMS 的监听端点. @Component public class MyService { @JmsListener(destination = "myDestination") public void processOrder(String data) { ... } } 上述示例的想法是,每当javax.jms.Destination &

《Spring 5官方文档》11集成测试 (三)

11.4.2 标准注解支持 以下注解为Spring TestContext 框架所有的配置提供标准语义支持.注意这些注解不仅限于测试,可以用在Spring框架的任意地方. @Autowired @Qualifier @Resource(javax.annotation)如果JSR-250存在 @ManagedBean(javax.annotation)如果JSR-250存在 @Inject(javax.inject)如果JSR-330存在 @Named(javax.inject)如果JSR-33

《Spring 5官方文档》翻译邀请

公司新的应用已经开始使用Spring 5,所以本月组织大家翻译<Spring 5 官方文档> SINGLE网页版  PDF版本. 如何领取 通过评论领取想要翻译的文章,每次领取一章或一节(根据内容长短),翻译完后再领取其他章节.领取完成之后,建议在一个星期内翻译完成,如果不能完成翻译,也欢迎你邀请其他同学和你一起完成翻译.请谨慎领取,并发网是非盈利组织,没办法去跟进每一篇译文的进展,所以很多文章领取了没有翻译,会导致文章长时间没人翻译. 如何提交? 翻译完成之后请登录到并发编程网后台,点击左上

《Spring 5 官方文档》16.ORM和数据访问(一)

16.1介绍一下Spring中的ORM Spring框架在实现资源管理.数据访问对象(DAO)层,和事务策略等方面,支持对Java持久化API(JPA)以及原生Hibernate的集成.以Hibernate举例来说,Spring有非常赞的IoC功能,可以解决许多典型的Hibernate配置和集成问题.开发者可以通过依赖注入来配置O-R(对象关系)映射组件支持的特性.Hibernate的这些特性可以参与Spring的资源和事务管理,并且符合Spring的通用事务和DAO层的异常体系.因此,Spri

《Spring 5 官方文档》16.ORM和数据访问(二)

16.3.4编程式事务划分 开发者可以在应用程序的更高级别上对事务进行标定,而不用考虑低级别的数据访问执行了多少操作.这样不会对业务服务的实现进行限制:只需要定义一个Spring的PlatformTransactionManager即可.当然,PlatformTransactionManager可以从多处获取,但最好是通过setTransactionManager(..)方法以Bean来注入,正如ProductDAO应该由setProductDao(..)方法配置一样.下面的代码显示Spring

《Spring Boot官方文档》16. 自动配置

16. 自动配置 Spring Boot的自动配置会尝试根据你添加进来的jar依赖来自动配置你的Spring应用.例如,如果HSQLDB在你的classpath路径上,你没有手动配置任何数据库连接实体类,我们还会自动配置内存数据库. 你可以有选择的实现自动配置,可以向 @Configuration上添加@EnableAutoConfiguration或者@SpringBootApplication注解来实现. 你应该只添加一个@EnableAutoConfiguration注解.我们通常建议你把

Spring Data 官方文档》4.7 Spring Data扩展

4.7 Spring Data扩展 这部分说明Spring Data一系列的扩展功能,可以使Spring Dta使用多样的上下文.目前大部分集成是针对Spring MVC. 4.7.1 Querydsl扩展 Querydsl是一个框架,通过它的流式API构建静态类型的SQL类查询.多个Spring Data模块通过QueryDslPredicateExecutor与Querydsl集成. 例29 QueryDslPredicateExecutor接口 1 public interface Que

《Spring 5官方文档》11集成测试 (二)

11.3 JDBC测试支持 org.springframework.test.jdbc是包含JdbcTestUtils的包,它是一个JDBC相关的工具方法集,意在简化标准数据库测试场景.特别地,JdbcTestUtils提供以下静态工具方法: countRowsInTable(..):统计给定表的行数. countRowsInTableWhere(..):使用提供的where语句进行筛选统计给定表的行数. deleteFromTables(..):删除特定表的全部数据. deleteFromTa

《Spring 5官方文档》电子邮件

29. 电子邮件 29.1 介绍 依赖库:使用Spring框架的邮件功能需要将JavaMail的Jar包添加到依赖中.这个库可以Maven中心找到:com.sun.mail:javax.mail. Spring提供了一个实用的发送电子邮件库,它为使用者屏蔽了邮件系统的底层细节和客户端的底层资源处理. Spring邮件相关功能在org.springframework.mail包下,其中MailSender是发送邮件的核心接口:SimpleMailMessage类是对邮件属性(发件人.收件人以等)进