JPA(Java Persistence API):Sun官方提出的Java持久化规范,定义了对象-关系映射(ORM)以及实体对象持久化的标准接口。Sun引入JPA出于两个原因:一、简化现有Java EE和Java SE应用开发工作;二、整合多种ORM框架(Hibernate、TopLink、JDO等),在Java开发平台上形成统一的ORM标准。

  Spring Data JPA:为简化JPA的开发提供帮助。EntityManager的创建与销毁、事务管理等代码被抽取出来,交由Spring统一管理,在没有特殊需求的情况下,开发人员不再需要关心这些;LocalContainerEntityManagerFactoryBean提供了非常灵活的配置方式,JPA规范中的配置信息(persistence.xml )可以由其以属性注入的方式进行配置;通过继承Repository接口,Spring可以为开发人员自动实现Dao层的大部分操作(增删改查、分页、审 计等)。

  

下面就介绍一下在实际项目中使用过的Spring Data JPA相关技术。首先看如何配置LocalContainerEntityManagerFactoryBean。

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan" value="org.mmh.entity" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.url">jdbc:mysql://localhost:3306/ttf</prop>
<prop key="hibernate.connection.username">root</prop>
<prop key="hibernate.connection.password">mmh</prop>
<prop key="hibernate.c3p0.min_size">10</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>

  Spring提供了三种方式建立EntityManagerFactory,LocalEntityManagerFactoryBean、LocalContainerEntityManagerFactoryBean和Obtaining an EntityManagerFactory from JNDI。LocalEntityManagerFactoryBean用于简单应用或测试,通过META-INF/persistence.xml整合其它ORM框架提供的JPA实现。Obtaining an EntityManagerFactory from JNDI用于Java EE应用服务器。LocalContainerEntityManagerFactoryBean用于独立运行的应用程序,它使Spring能够完全控制JPA。通过该方式,开发人员能在一个文件内完成JPA的所有配置。packagesToScan属性使EntityManagerFactory自动扫描指定包内的实体类。jpaVendorAdapter属性定义Hibernate为JPA的提供者,这里Spring采用了适配器模式将Hibernate集成进来。jpaProperties属性详细定义了Hibernate的配置参数,这个配置方式与常规的做法不同。一般来讲,数据库连接池会被单独定义,然后集成到JPA中,而在这里是通过Hibernate来管理所有涉及数据库的配置,这样不仅简化了配置,而且能够使模块之间的关系更清晰。再加上Hibernate早已弃用了dbcp,并自己集成了c3p0,所以通过Hibernate自身来管理数据库连接池应该是最稳妥的方式。Hibernate本身有连接池,官网上介绍它的连接池功能只是用作开发和测试,在实际的项目中需要集成第三方产品,通过设置hibernate.c3p0.*属性就能启动c3p0连接池。

  然后再进行JPA的事务管理和Dao配置。

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean> <tx:annotation-driven transaction-manager="transactionManager" /> <jpa:repositories base-package="org.mmh.dao"
transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory" />

  Spring为JPA提供了专门的事务管理器,JpaTransactionManager,并且通过tx:annotation-driven标签自动扫描代码中添加了@Transactional的类和public成员函数。jpa:repositories标签能够自动为指定包内的继承了Repository<T, ID extends Serializable>的Dao接口提供事务处理功能。

  对于事务管理需要专门说明一下。首先,管理的对象必须是可以进行事务操作的资源,例如数据库、消息队列、缓存等,并且这些资源要提供事务管理的功能。使用MyISAM引擎的MySQL 数据库本身不支持事务,所以无须在Spring中配置事务管理器,因为即使配置了,也没有实际用处。但Hibernate的事务管理和一级缓存有密切的关 系:当调用save、update等方法时,Hibernate并不直接向数据库发送SQL语句,而是在提交事务或flush一级缓存时才真正向数据库发送SQL。所以,即使数据库不支持事务,Hibernate的事务管理也是有一定好处的,不会对数据操作的效率造成负面影响。也就是说Spring集成Hibernate后,不论数据库是否支持事务,都可以进行事务管理的操作。甚至当Hibernate的connection.autocommit为true时,Spring仍然能够控制事务。

  另外,事务的属性可以通过@Transactional标签进行设置。比较重要的属性:传播行为,默认是PROPAGATION_REQUIRED,它表示有事务环境时就加入到已有的环境中,没有就新建一个。比如,在Service层声明了事务管理,同时Dao层因为继承Repository接口也默认声明了事务管理。当Service层中的函数调用Dao层中的函数时,两个函数共用一个事务,即外层函数的事务。Spring中事务传播行为有七种,各有用途,详细说明可以参考相关资料。事务操作,Repository接口定义的增删改默认是read和write,而查询默认为只读。事务回滚,默认是对unchecked异常回滚,对checked异常不回滚。事务隔离级别,默认是DEFAULT,它与数据库本身事务操作有关,如果没有特殊要求,可以忽略它。事务超时,默认是无,可以设置以秒单位的时间。

  写一段代码测试一下上面讲述的内容。主程序初始化Spring容器,然后获取处理账户的业务层Bean,最后保存一个账户实体。

package org.mmh.main;

import org.mmh.entity.Account;
import org.mmh.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext(
"appContext.xml"); AccountService service = context.getBean(AccountService.class); Account account = new Account();
account.setUserName("yzp");
account.setPassword("123");
account.setPhoneSN("1234567890"); service.saveAccount(account);
}
}

  在业务层中,实现一个处理账户的业务,只有保存账户的功能。为了验证Spring事务管理的有效性,在保存完一个新账户后打印出数据库中账户的记录数,然后执行一个除以0的操作,系统会抛出unchecked异常,最后导致事务回滚,在数据库里查询不到新的账户记录。

package org.mmh.service;

import org.mmh.dao.AccountDao;
import org.mmh.entity.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; @Service
@Transactional
public class AccountService { @Autowired
private AccountDao accountDao; public void saveAccount(Account account) throws Exception {
accountDao.save(account); System.out.println("账户记录数: " + accountDao.count()); int foo = 1 / 0;
}
}
//输出结果:
/*
* Hibernate: select account0_.userName as userName1_0_0_, account0_.password as password2_0_0_,
* account0_.phoneSN as phoneSN3_0_0_ from t_account account0_ where account0_.userName=?
* Hibernate: insert into t_account (password, phoneSN, userName) values (?, ?, ?)
* Hibernate: select count(*) as col_0_0_ from t_account account0_
* 账户记录数: 3
* Exception in thread "main" java.lang.ArithmeticException: / by zero
*/

  以上是Spring JPA以及事务管理的默认配置,从效果来看,其功能已经可以满足大多情况下的需求了。在实际项目中最有可能改动的地方也就是让checked异常也能实现事务回滚。要实现这个功能很简单,标记@Transactional(rollbackFor=Exception.class)。这样所有继承Exception的异常都能触发事务回滚了。当然也可以选择在配置文件中通过AOP声明事务。熟悉AOP的话,配置起来也很简单,原理跟注释声明事务一样。

JPA in Spring的更多相关文章

  1. 【Hades】ades是一个开源库,基于JPA和Spring构建,通过减少开发工作量显著的改进了数据访问层的实现

    几乎每个应用系统都需要通过访问数据来完成工作.要想使用领域设计方法,你就需要为实体类定义和构建资源库来实现领域对象的持久化.目前开发人员经常使用JPA来实现持久化库.JPA让持久化变得非常容易,但是仍 ...

  2. jdbc、jpa、spring data jpa、hibernate、mybatis之间的关系及区别

    基础概念 jdbc(Java DataBase Connectivity)是java连接数据库操作的原生接口.JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型.作为A ...

  3. MyEclipse持续性开发教程:用JPA和Spring管理数据(五)

    MyEclipse 3.15 Style——在线购买低至75折!火爆开抢>> [MyEclipse最新版下载] 本教程介绍了MyEclipse中的一些基于JPA / Spring的功能.有 ...

  4. MyEclipse持续性开发教程:用JPA和Spring管理数据(四)

    MyEclipse红运年货节 在线购买低至69折!火爆开抢>> [MyEclipse最新版下载] 本教程介绍了MyEclipse中的一些基于JPA / Spring的功能.有关设置JPA项 ...

  5. MyEclipse持续性开发教程:用JPA和Spring管理数据(三)

    MyEclipse红运年货节 在线购买低至69折!火爆开抢>> [MyEclipse最新版下载] 本教程介绍了MyEclipse中的一些基于JPA / Spring的功能.有关设置JPA项 ...

  6. MyEclipse持续性开发教程:用JPA和Spring管理数据(二)

    MyEclipse红运年货节 在线购买低至69折!火爆开抢>> [MyEclipse最新版下载] 本教程介绍了MyEclipse中的一些基于JPA / Spring的功能.有关设置JPA项 ...

  7. MyEclipse持续性开发教程:用JPA和Spring管理数据(一)

    MyEclipse开年钜惠 在线购买低至75折!立即开抢>> [MyEclipse最新版下载] 本教程介绍了MyEclipse中的一些基于JPA / Spring的功能.有关设置JPA项目 ...

  8. 使用Spring Data JPA的Spring Boot

    本文教你开始使用Spring Data JPA.来自优锐课JAVA架构专业讲师精心整理. 欢迎使用带有Spring Data JPA的Spring Boot教程!在本教程中,我们将看到Spring D ...

  9. Spring Data JPA 整合Spring

    1.1   Spring Data JPA 与 JPA和hibernate之间的关系 JPA是一套规范,内部是有接口和抽象类组成的.hibernate是一套成熟的ORM框架,而且Hibernate实现 ...

  10. Spring Data JPA简介 Spring Data JPA特点

    Spring Data JPA 是Spring基于ORM框架.JPA规范的基础上封装的一套JPA 应用框架,底层使用了Hibernate 的JPA技术实现,可使开发者用极简的代码即可实现对数据的访问和 ...

随机推荐

  1. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

  2. tomcat下jsp要加工程名后缀才能访问的问题解决

    今天发现一个部署的项目,在tomcat中配置了去掉工程名,直接通过域名访问.配置后其它的html.动态请求等都可以不带工程名访问,但是只要访问jsp页面就报404错误,加上工程名访问jsp却又正常. ...

  3. USACO翻译:USACO 2014 JAN三题(1)

    USACO 2014 JAN 一.题目概览 中文题目名称 滑雪场设计 滑雪降速 滑雪场评级 英文题目名称 skidesign slowdown skilevel 可执行文件名 skidesign sl ...

  4. LR11破解License

    golba-65000: AEACFSJI-YJKJKJJKEJIJD-BCLBR golba-100: AEAMAUIK-YAFEKEKJJKEEA-BCJGI web-10000: AEABEXF ...

  5. [uva12170]Easy Climb

    还是挺难的一个题,看了书上的解析以后还是不会写,后来翻了代码仓库,发现lrj又用了一些玄学的优化技巧. #include <algorithm> #include <iostream ...

  6. Servlet中的常用类以及常用方法

    A:ServletConfig:用于读取Servlet在web.xml中配置的一些信息. getServletName(); getInitParameter();只能是Servlet自身下的参数设置 ...

  7. +Load和+initialize方法解析

    http://www.cnblogs.com/ider/archive/2012/09/29/objective_c_load_vs_initialize.html

  8. H264编码原理以及I帧、B和P帧详解

    H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的理论依据是:参照一段时间内图像的统计结果表明,在相邻几幅图像画面中,一般有差别的像素只有10%以内的点 ...

  9. Preference Screen 首选项

     设置Preference Screen (res\xml\userpreferences.xml) <?xml version="1.0" encoding="u ...

  10. angular service provider

    关于  angular service factory  provider 方面有很多,我也来写一篇加深下印象 provider 是一切方法的基础,所以功能也最强,provider 用来定义一个可以被 ...