知识点
相关文章
更多最近更新
更多【第八章】 对ORM的支持 之 8.4 集成JPA ——跟我学spring3
2019-03-01 14:48|来源: 开涛
8.4 集成JPA
JPA全称为Java持久性API(Java Persistence API),JPA是Java EE 5标准之一,是一个ORM规范,由厂商来实现该规范,目前有Hibernate、OpenJPA、TopLink、EclipseJPA等实现。
8.4.1 如何集成
Spring目前提供集成Hibernate、OpenJPA、TopLink、EclipseJPA四个JPA标准实现。
Spring通过使用如下Bean进行集成JPA(EntityManagerFactory):
LocalEntityManagerFactoryBean:适用于那些仅使用JPA进行数据访问的项目,该FactoryBean将根据JPA PersistenceProvider自动检测配置文件进行工作,一般从“META-INF/persistence.xml”读取配置信息,这种方式最简单,但不能设置Spring中定义的DataSource,且不支持Spring管理的全局事务,而且JPA 实现商可能在JVM启动时依赖于VM agent从而允许它们进行持久化类字节码转换(不同的实现厂商要求不同,需要时阅读其文档),不建议使用这种方式;
persistenceUnitName:指定持久化单元的名称;
使用方式:
从JNDI中获取:用于从Java EE服务器获取指定的EntityManagerFactory,这种方式在进行Spring事务管理时一般要使用JTA事务管理;
使用方式:
此处需要使用“jee”命名标签,且使用<jee:jndi-lookup>标签进行JNDI查找,“jndi-name”属性用于指定JNDI名字。
LocalContainerEntityManagerFactoryBean:适用于所有环境的FactoryBean,能全面控制EntityManagerFactory配置,如指定Spring定义的DataSource等等。
persistenceUnitManager:用于获取JPA持久化单元,默认实现DefaultPersistenceUnitManager用于解决多配置文件情况
dataSource:用于指定Spring定义的数据源;
persistenceXmlLocation:用于指定JPA配置文件,对于对配置文件情况请选择设置persistenceUnitManager属性来解决;
persistenceUnitName:用于指定持久化单元名字;
persistenceProvider:用于指定持久化实现厂商类;如Hibernate为org.hibernate.ejb.HibernatePersistence类;
jpaVendorAdapter:用于设置实现厂商JPA实现的特定属性,如设置Hibernate的是否自动生成DDL的属性generateDdl;这些属性是厂商特定的,因此最好在这里设置;目前Spring提供HibernateJpaVendorAdapter、OpenJpaVendorAdapter、EclipseLinkJpaVendorAdapter、TopLinkJpaVendorAdapter、OpenJpaVendorAdapter四个实现。其中最重要的属性是“database”,用来指定使用的数据库类型,从而能根据数据库类型来决定比如如何将数据库特定异常转换为Spring的一致性异常,目前支持如下数据库(DB2、DERBY、H2、HSQL、INFORMIX、MYSQL、ORACLE、POSTGRESQL、SQL_SERVER、SYBASE)。
jpaDialect:用于指定一些高级特性,如事务管理,获取具有事务功能的连接对象等,目前Spring提供HibernateJpaDialect、OpenJpaDialect 、EclipseLinkJpaDialect、TopLinkJpaDialect、和DefaultJpaDialect实现,注意DefaultJpaDialect不提供任何功能,因此在使用特定实现厂商JPA实现时需要指定JpaDialect实现,如使用Hibernate就使用HibernateJpaDialect。当指定jpaVendorAdapter属性时可以不指定jpaDialect,会自动设置相应的JpaDialect实现;
jpaProperties和jpaPropertyMap:指定JPA属性;如Hibernate中指定是否显示SQL的“hibernate.show_sql”属性,对于jpaProperties设置的属性自动会放进jpaPropertyMap中;
loadTimeWeaver:用于指定LoadTimeWeaver实现,从而允许JPA 加载时修改相应的类文件。具体使用得参考相应的JPA规范实现厂商文档,如Hibernate就不需要指定loadTimeWeaver。
接下来学习一下Spring如何集成JPA吧:
1、准备jar包,从下载的hibernate-distribution-3.6.0.Final包中获取如下Hibernate需要的jar包从而支持JPA:
2、对象模型定义,此处使用UserModel2:
注意此处使用的所有注解都是位于javax.persistence包下,如使用@org.hibernate.annotations.Entity 而非@javax.persistence. Entity将导致JPA不能正常工作。
1、 JPA配置定义(chapter8/persistence.xml),定义对象和数据库之间的映射:
在JPA配置文件中,我们指定要持久化单元名字,和事务类型,其他都将在Spring中配置。
2、 数据源定义,此处使用第7章的配置文件,即“chapter7/ applicationContext-resources.xml”文件。
3、 EntityManagerFactory配置定义(chapter8/applicationContext-jpa.xml):
LocalContainerEntityManagerFactoryBean:指定使用本地容器管理EntityManagerFactory,从而进行细粒度控制;
dataSource属性指定使用Spring定义的数据源;
persistenceXmlLocation指定JPA配置文件为chapter8/persistence.xml,且该配置文件非常简单,具体配置完全在Spring中进行;
persistenceUnitName指定持久化单元名字,即JPA配置文件中指定的;
persistenceProvider:指定JPA持久化提供商,此处使用Hibernate实现HibernatePersistence类;
jpaVendorAdapter:指定实现厂商专用特性,即generateDdl= false表示不自动生成DDL,database= HSQL表示使用hsqldb数据库;
jpaDialect:如果指定jpaVendorAdapter此属性可选,此处为HibernateJpaDialect;
jpaProperties:此处指定“hibernate.show_sql =true”表示在日志系统debug级别下将打印所有生成的SQL。
4、 获取EntityManagerFactory:
此处我们使用了chapter7/applicationContext-resources.xml定义的“dataSource”数据源,通过ctx.getBean(EntityManagerFactory.class)获取EntityManagerFactory。
5、 通过EntityManagerFactory获取EntityManager进行创建和删除表:
使用EntityManagerFactory创建EntityManager,然后通过EntityManager对象的createNativeQuery创建本地SQL执行创建和删除表。
6、 使用EntityManagerFactory获取EntityManager对象进行持久化数据:
使用EntityManagerFactory获取EntityManager进行操作,看到这还能忍受冗长的代码和事务管理吗?Spring同样提供JpaTemplate模板类来简化这些操作。
大家有没有注意到此处的模型对象能自动映射到数据库,这是因为Hibernate JPA实现默认自动扫描类路径中的@Entity注解类及*.hbm.xml映射文件,可以通过更改Hibernate JPA属性“hibernate.ejb.resource_scanner”,并指定org.hibernate.ejb.packaging.Scanner接口实现来定制新的扫描策略。
8.4.2 使用JpaTemplate
JpaTemplate模板类用于简化事务管理及常见操作,类似于JdbcTemplate模板类,对于复杂操作通过提供JpaCallback回调接口来允许更复杂的操作。
接下来示例一下JpaTemplate的使用:
1、修改Spring配置文件(chapter8/applicationContext-jpa.xml),添加JPA事务管理器:
txManager:指定事务管理器,JPA使用JpaTransactionManager事务管理器实现,通过entityManagerFactory指定EntityManagerFactory;用于支持Java SE环境的JPA扩展的持久化上下文(EXTENDED Persistence Context)。
2、修改JPATest类,添加类变量ctx,用于后边使用其获取事务管理器使用:
3)JpaTemplate模板类使用:
jpaTemplate:可通过new JpaTemplate(entityManagerFactory)方式创建;
txManager:通过ctx.getBean(PlatformTransactionManager.class)获取事务管理器;
TransactionTemplate:通过new TransactionTemplate(txManager)创建事务模板对象,并通过execute方法执行TransactionCallback回调中的doInTransaction方法中定义需要执行的操作,从而将由模板类通过txManager事务管理器来进行事务管理,此处是调用jpaTemplate对象的persist方法进行持久化;
jpaTemplate.persist():根据JPA规范,在JPA扩展的持久化上下文,该操作必须运行在事务环境,还有persist()、 merge()、remove()操作也必须运行在事务环境;
jpaTemplate.find():根据JPA规范,该操作无需运行在事务环境,还有find()、getReference()、 refresh()、detach()和查询操作都无需运行在事务环境。
此实例与Hibernate和Ibatis有所区别,通过JpaTemplate模板类进行如持久化等操作时必须有运行在事务环境中,否则可能抛出如下异常或警告:
“javax.persistence.TransactionRequiredException:Executing an update/delete query”:表示没有事务支持,不能执行更新或删除操作;
警告“delaying identity-insert due to no transaction in progress”:需要在日志系统启动debug模式才能看到,表示在无事务环境中无法进行持久化,而选择了延迟标识插入。
以上异常和警告是没有事务造成的,也是最让人困惑的问题,需要大家注意。
8.4.3 集成JPA及最佳实践
类似于JdbcDaoSupport类,Spring对JPA也提供了JpaDaoSupport类来支持一致的数据库访问。JpaDaoSupport也是DaoSupport实现:
接下来示例一下Spring集成JPA的最佳实践:
1、 定义Dao接口,此处使用cn.javass.spring.chapter7.dao. IUserDao:
2、 定义Dao接口实现,此处是JPA实现:
此处注意首先JPA实现放在dao.jpa包里,其次实现类命名如UserJpaDaoImpl,即×××JpaDaoImpl,当然如果自己有更好的命名规范可以遵循自己的,此处只是提个建议。
另外在类上添加了@Transactional注解表示该类的所有方法将在调用时需要事务支持,propagation传播属性为Propagation.REQUIRED表示事务是必需的,如果执行该类的方法没有开启事务,将开启一个新的事务。
3、进行资源配置,使用resources/chapter7/applicationContext-resources.xml:
4、dao定义配置,在chapter8/applicationContext-jpa.xml中添加如下配置:
4.1、首先添加tx命名空间用于支持事务:
4.2、为@Transactional注解事务开启事务支持:
只为类添加@Transactional 注解是不能支持事务的,需要通过<tx:annotation-driven>标签来开启事务支持,其中txManager属性指定事务管理器。
4.3、配置DAO Bean:
首先定义抽象的abstractDao,其有一个entityManagerFactory属性,从而可以让继承的子类自动继承entityManagerFactory属性注入;然后定义userDao,且继承abstractDao,从而继承entityManagerFactory注入;我们在此给配置文件命名为applicationContext-jpa.xml表示JPA实现。
5、最后测试一下吧(cn.javass.spring.chapter8. JPATest):
和Spring JDBC框架的最佳实践完全一样,除了使用applicationContext-jpa.xml代替了applicationContext-jdbc.xml,其他完全一样。也就是说,DAO层的实现替换可以透明化。
还有与集成其他ORM框架不同的是JPA在进行持久化或更新数据库操作时需要事务支持。
8.4.4 Spring+JPA的CRUD
Spring+JPA CRUD(增删改查)也相当简单,让我们直接看具体示例吧:
对于增删改必须运行在事务环境,因此我们使用TransactionTemplate事务模板类来支持事务。
持久化:使用JpaTemplate 类的persist方法持久化模型对象;
更新:对于持久化状态的模型对象直接修改属性,调用flush方法即可更新到数据库,在一些场合时flush方法调用可选,如执行一个查询操作等,具体请参考相关文档;
查询:可以使用find方法执行JPA QL查询;
删除:使用remove方法删除一个持久化状态的模型对象。
Spring集成JPA进行增删改查也相当简单,但本文介绍的稍微复杂一点,因为牵扯到编程式事务,如果采用声明式事务将和集成Hibernate方式一样简洁。
本文链接:领悟书生教程网,转自http://sishuok.com/forum/blogPost/list/0/2500.html
相关问答
更多-
Java 2 实用教程第八章[2023-07-22]
请问你是想把你输入的数字保存到文本区的,,, 而大于1000个字符后,,,你无法确定是否需要保存到文本区吗? 对于以上, 我的理解是,你完全可以设定文本框最大字符长度。。 -
20岁学编程,晚吗?我的前途如何?[2022-11-24]
很有上进心的孩子。所以有件事情你一定要及早知道。程序员这个职位,其实含义很广。简单点去理解,3个月的时间,懂一点皮毛,就可以。但是你会的越多,就越知道自己不会的更多。所以不要求速度的门槛,要筑造好坚实的基础。你学的教材我不知道,但是几乎所有的书,只能教给你手段,不能带给你思想。而这正是程序员和IT民工的差别所在。20开始学不晚。十分不晚。所以你应该专心学习,避免急功近利。 如果你已经能够实际的工作,那么继续提高除了熟练度和开拓编程思想以外,还包括两个重要方向:一是横向学习。比如你主业是c++,在你达到一定高 ... -
Swift不支持SDK'iPhoneSimulator8.4.sdk'(Swift does not support the SDK 'iPhoneSimulator8.4.sdk')[2022-06-09]
这发生在我同时安装了Xcode 7和6.4之后,而在自动更新之后,我只剩下7.0.1 。 一种迹象表明,某些东西搞砸了xcodebuild -sdk -version输出: xcodebuild[29131:8243992] [MT] DVTSDK: Warning: SDK path collision for path '8.4不支持每列归类(或用于比较和排序的归类“表达式”)。 你将不得不升级到9.1(无论如何这是个好主意) 8.4 does not support per column collations (or collation "expressions" for comparing and sorting). You will have to upgrade to 9.1 (which is a good idea anyway)ORM支持Hadoop DB(ORM support for Hadoop DB)[2021-10-13]
Apache Gora开源框架为大数据提供了内存数据模型和持久性。 Gora支持持久存储到列存储,键值存储,文档存储和RDBMS,并通过广泛的Apache Hadoop™MapReduce支持分析数据。 - 请参阅: http : //gora.apache.org/#sthash.aHUqfiFl.dpuf The Apache Gora open source framework provides an in-memory data model and persistence for big data. ...JPA,Hibernate和Spring集成:表不存在错误(JPA, Hibernate and Spring integration : Table doesn't exist Error)[2022-01-04]
我建议将表名更改为Client实体类中的正确大小写。 使用@Table(name="clients")而不是@Table(name="CLIENTS") 。 I would suggest to change the table name to the correct case in the Client entity class. Use @Table(name="clients") instead of @Table(name="CLIENTS").是。 支持iOS 8。 测试云概述 显示iOS 8.4设备的示例场景 支持0.14.0但是,您应该(始终)更新到最新版本的Calabash iOS - 目前为0.14.3。 Yes. iOS 8 is supported. Test Cloud Overview Sample Scenario with iOS 8.4 devices showing 0.14.0 is supported but, you should (always) update to the most recent version ...将ice / ace:dataTable与JPA和请求范围的bean集成(Integrating ice/ace:dataTable with JPA and request-scoped beans)[2022-08-21]
如果你问我,当你的要求似乎为一些有点发烧友的东西尖叫时,主要的错误似乎是坚持几乎裸露的Tomcat。 通常情况下,当你不需要“所有其他东西”时你使用Tomcat,所以当你需要它时,为什么继续使用一个裸Tomcat? 也就是说,这种模式并不那么困难。 有一个视图范围的支持bean 获取@PostConstruct的初始数据 - (当没有像ID这样的参数时)或PreRenderViewEvent方法结合视图参数 使用单独的Service类,该类使用实体管理器来获取和保存数据 使实体管理器“事务范围” 没有EJB ...集成JPA和SpringIOc(integrating JPA and SpringIOc)[2022-04-05]
org.springframework.orm.jpa.LocalEntityManagerFactoryBean没有定义dataSource / getDataSource()字段/方法。 这就是为什么你得到那个例外。 请改用LocalContainerEntityManagerFactoryBean 这可能会对你有所帮助 org.springframework.orm.jpa.LocalEntityManagerFactoryBean does not have a dataSource/ getDat ...