JPA介绍与实例

来源:互联网 发布:html 数组 编辑:程序博客网 时间:2024/06/09 17:18

JPA的起源

对象关系映射ORM(Object-Relation Mapping)是用来将对象和对象之间的关系对应到数据库中表与表之间的关系的一种模式。

ORM框架能够将Java对象映射到关系数据库,能够直接持久化复杂的Java对象。ORM框架的出现,使开发者从数据库编程中解脱出来,把更多的精力放在了业务模型与业务逻辑上。目前比较流行的ORM框架有Hibernate、iBatis、TopLink等。在JPA规范之前,由于没有官方的标准,使得各ORM框架之间的API差别很大,使用了某种ORM框架的系统会严重受制于该ORM的标准。


基于此,Sun引入新的JPA ORM,主要的原因有:其一,简化现有Java EE和Java SE应用开发工作;其二,Sun希望整合ORM技术,实现天下归一。JPA-Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它又不限于EJB 3.0,你可以在Web应用、甚至桌面应用中使用


官方介绍与学习网址:
http://www.oracle.com/technetwork/java/javaee/tech/persistence-jsp-140049.html



JPA包含的技术

JPA包含3个方面的技术:
1)ORM映射元数据
JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
2)API
用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
3)查询语言
这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。


与ORM框架的关系

JPA本身是一个规范,基于此规范实现的产品有:Hibernate, Eclipselink, Toplink, Spring Data JPA, etc.
1)JPA与Hibernate的关系
I、JPA本质上是一种ORM规范,并未提供ORM实现,其具体实现由其他厂商来提供。程序员若使用JPA,仍然需要选择JPA的实现框架。
Hibernate是一个面向Java环境的对象关系数据库映射工具,即ORM工具。它对JDBC API进行了封装,负责Java对象的持久化,在分层的软件架构中它位于持久化层,封装了所有数据访问细节,使业务逻辑层可以专注于实现业务逻辑。Hibernate不仅仅管理Java类到数据库表的映射,还提供了数据查询和获得数据的方法,可以大幅度减少开发时人工使用SQL和JDBC处理数据的时间。
II、Hibernate 3.2以后的版本开始支持JPA,其中,涉及JPA的子项目有三个,它们分别是:
 Hibernate Core Hibernate框架的核心实现。
 Hibernate Annotations 支持JDK 5.0的注释。
 Hibernate EntityManager 支持JPA的实现。
   JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。



JPA之实体与实体管理器

1)、实体(Entity)
   JPA能够将普通的Java对象(有时被称作POJO) 映射到数据库,这些Java对象被称作Entity(实体)。
(1)、一个实体的定义符合JavaBean的规范,因此常常称为实体Bean。实体Bean的每个属性都定义为私有的,并且有对应的Setter和Getter方法。JPA将实体映射到数据库有两种方法,一种是基于xml文件,一种是基于标注。
(2)、采用标注方法映射的实体Bean,在类的定义中还包含了映射信息,这些映射信息都是通过标注表示的。下面是用户类的实体Bean。
@Entity
@Table(name = "USER")
public class User implements Serializable {
}
2)、实体管理器(EntityManager)
  EntityManager是应用程序访问持久化上下文中的实体的接口,是Java实体对象与数据库交互的中介。它负责管理一组对应的实体,包括这组实体的CRUD操作。同时,实体管理器也负责与持久化上下文(Persistence Context)进行交互,可以实现对实体不同状态进行转换操作等。


3)、如何获取EntityManager
(1)、实体管理器要通过实体管理器工厂建立。但是,当使用容器托管的实体管理器(在Java EE环境中)时,应用不和实体管理器工厂交互
。实体管理器直接通过依赖注入或JNDI获得,容器负责与实体管理器工厂交互。
(2)、注入实体管理器 可以用@PersitenceContext标注来注入EntityManager,其属性 type指明持久化上下文的作用范围,默认是
TARNSACTION。若选择EXTENDED(扩展的方式),可使得多次调用使用同样的上下文,它的意义在于对有状态的Bean可以跨事务操作实体;
unitName(可选)用于指定一个持久性单元。
(3)、当使用应用托管的实体管理器时,应用必须使用实体管理器工厂来管理实体管理器和持久化上下文的生命周期。EntityManagerFactory
接口供应用来创建应用管理的实体管理器。EntityManagerFactory的方法都是线程安全的。注入实体管理工厂 在Java EE容器内,可以用
@PersistenceUnit标注注入或者通过JNDI查找获得EntityManagerFactory,其unitName属性(可选)用于指明使用哪个持久性单元。

EntityManagerFactory-这是一个EntityManager的工厂类。它创建并管理多个EntityManager实例。
EntityManager-这是一个接口,它管理的持久化操作的对象。它的工作原理类似工厂的查询实例。
Entity-实体是持久性对象是存储在数据库中的记录。
EntityTransaction-它与EntityManager是一对一的关系。对于每一个EntityManager,操作是由EntityTransaction类维护。
Persistence-这个类包含静态方法来获取EntityManagerFactory实例。
Query-该接口由每个JPA供应商,能够获得符合标准的关系对象。


EntityManagerFactory和EntityManager的关系是1对多。这是一个工厂类EntityManager实例。


EntityManager和EntityTransaction之间的关系是1对1。对于每个EntityManager操作,只有一个EntityTransaction实例。


EntityManager和Query之间的关系是1对多。查询数众多可以使用一个EntityManager实例执行。


EntityManager实体之间的关系是1对多。一个EntityManager实例可以管理多个实体。



基于Hibernate 的实例


首先要进行的就是开发环境的搭建,简单介绍如下:
1. 下载hibernate, 本篇使用的版本是 hibernate-release-4.2.2.Final
2. 在Eclipse中创建一个java Project, 简单出发,将hibernate中lib\required下的所有jar档放入项目的lib.
3. 将lib\jpa 目录下的hibernate-entitymanager-4.2.2.Final.jar放到classpath,否则会出现No Persistence provider for EntityManager的错误
4. 将数据库的driver的jar包放入, 这里使用的是Oracle, 所以文件是 ojdbc14.jar
3. 因为使用junit 测试, 下载一个junit ,目前版本是4
https://sourceforge.net/projects/junit/files/latest/download


使用JPA进行数据操作,基本的步骤如下:
(1)配置服务器数据源。
(2)建立持久性单元。
(3)建立实体类。
(4)建立实体管理器。
(5)操作实体。
(6)关闭实体管理器。


1. 配置数据库
在src目录下建立META-INF 目录, 下面建立persistence.xml的文件, 内容如下:

<?xml version="1.0" encoding="UTF-8"?><persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_version=1"><persistence-unit name="myOracleJPA" transaction-type="RESOURCE_LOCAL"><properties><property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" /><property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver" /><property name="hibernate.connection.username" value="oscar999" /><property name="hibernate.connection.password" value="oscar999" /><property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:orcl" /><property name="hibernate.max_fetch_depth" value="3" /><property name="hibernate.hbm2ddl.auto" value="update" /></properties></persistence-unit></persistence>

备注:
1)persistence.xml文件的位置决定持久性的根(Persistence Root)。持久性的根为JAR文件或者包含META-INF目录(前提是persistence.xml位于此)的目录。一般将这个persistence.xml文件放在src下的META-INF中。命名及位置都不能变
2)不同数据库及不同的版本配置上会有部分差异。


2.建立实体类
这里建立User的用户实体类。

/**    * @Title: User.java * @Package com.oscar999.jpa * @Description:  * @author oscar999  * @date 2017-9-19 上午9:17:37 * @version V1.0    */package com.oscar999.jpa;import java.io.Serializable;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;/** * @author oscar999 *  */@Entity@Table(name="USER_TEST")public class User implements Serializable {/** *  */private static final long serialVersionUID = 1L;@Id@GeneratedValue(strategy = GenerationType.AUTO)private int id;private String userName;private String passWord;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassWord() {return passWord;}public void setPassWord(String passWord) {this.passWord = passWord;}}

一般状况下Table和Column可以不进行设置。不设置的话默认以类的名字和属性的名字作为表和栏位的名字。
这里User属于系统表, 所以使用Table来进行表名的制定。
栏位名同理, 使用Column标签指定。


3. 创建表测试(基于JUnit)

/**    * @Title: JPATest.java * @Package com.oscar999.jpa * @Description: TODO * @author oscar999  * @date 2017-9-19 下午2:49:33 * @version V1.0    */package com.oscar999.jpa;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.junit.Before;import org.junit.Test;/** * @author oscar999 *  */public class JPATest {@Beforepublic void setUp() throws Exception {}@Testpublic void createTable() {EntityManagerFactory factory = Persistence.createEntityManagerFactory("myOracleJPA");factory.close();}}

运行之后, 表就被创建出来了。


其他增删改查的功能如下:


/**    * @Title: JPATest.java * @Package com.oscar999.jpa * @Description: TODO * @author oscar999  * @date 2017-9-19 下午2:49:33 * @version V1.0    */package com.oscar999.jpa;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.junit.Before;import org.junit.Test;/** * @author oscar999 *  */public class JPATest {@Beforepublic void setUp() throws Exception {}// @Testpublic void createTable() {EntityManagerFactory factory = Persistence.createEntityManagerFactory("myOracleJPA");factory.close();}//@Testpublic void create() {EntityManagerFactory factory = Persistence.createEntityManagerFactory("myOracleJPA");EntityManager em = factory.createEntityManager();em.getTransaction().begin();User user = new User();user.setUserName("Zhang Fei");user.setPassWord("123456");em.persist(user);em.getTransaction().commit();em.close();factory.close();}//@Testpublic void update() {EntityManagerFactory factory = Persistence.createEntityManagerFactory("myOracleJPA");EntityManager em = factory.createEntityManager();em.getTransaction().begin();User user = em.find(User.class, 1);user.setPassWord("111111");em.getTransaction().commit();em.close();factory.close();}@Testpublic void retrieve() {EntityManagerFactory factory = Persistence.createEntityManagerFactory("myOracleJPA");EntityManager em = factory.createEntityManager();User user = em.find(User.class, 1);System.out.println(user.getUserName());em.close();factory.close();}//@Testpublic void delete() {EntityManagerFactory factory = Persistence.createEntityManagerFactory("myOracleJPA");EntityManager em = factory.createEntityManager();em.getTransaction().begin();User user = em.find(User.class, 1);em.remove(user);em.getTransaction().commit();em.close();factory.close();}}




原创粉丝点击