JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA 是 JCP定义的一种规范,要使用此规范,必需配合该规范的实现,开源实现有 apache的 openjpa,还有使用更广泛的hibernate jpa实现。
JPA是目前比较流行的一种ORM技术之一,所以他拥有ORM技术的各种特点,当然他还有自己的一些优势:
1 标准化
JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问 API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。
2 对容器级特性的支持
JPA 框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。
3 简单易用,集成方便
JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释;JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成。
4 可媲美JDBC的查询能力
JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。
5 支持面向对象的高级特性
JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。
Java示例
JPA程序依赖 javax.persistence API,本示例的pom文件为:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.1.0.Final</version>
</dependency>
此依赖会隐式地添加javax.
persistence相关依赖
entity代码:
package ejb.jpa;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "STUDENT")
public class User {
@Id
@Column(name = "ID")
private String id;
@Column(name = "NAME")
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
测试代码:
package ejb.jpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.List;
public class Main {
static EntityManagerFactory emf = Persistence.createEntityManagerFactory("myJPA");
static EntityManager em = emf.createEntityManager();
public static void main(String[] args) {
User person = new User(); //person为new状态
person.setId("aaaaa");
person.setName("zhang san");
em.persist(person); //持久化实体
add(person);
System.out.println("user id:" + person.getId());
User user = find(person.getId());
System.out.println(user);
List<User> all = findAll();
for (User u : all) {
System.out.println(u);
}
// close
em.close();
emf.close();
}
// 添加用户的方法
public static void add(User user) {
em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit();
}
// 查询用户的方法
public static User find(Object id) {
User user = em.find(User.class, id);
return user;
}
public static List<User> findAll() {
List<User> users = em.createQuery("select u from User u")
.getResultList();
return users;
}
}
JPA需要的配置文件:persistence.xml (注意:此文件必需放到类路径的根路径的META-INF文件夹下)
<?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_2_0.xsd">
<!-- 为持久化单元取名为 myJPA -->
<persistence-unit name="myJPA" transaction-type="RESOURCE_LOCAL">
<!--可以指定,如果不指定则从META-INF/services加载-->
<!--<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>-->
<!-- <class>com.micmiu.hibernate.jpa.UserInfo</class> -->
<!--<provider>com.tongweb.openjpa.persistence.PersistenceProviderImpl</provider>-->
<!--<jta-data-source>MyDataSource</jta-data-source>-->
<!-- class 定义指定持久化的实体类 注意配置属性hibernate.archive.autodetection=false -->
<!--<class>jpa.User</class>-->
<properties>
<property name="hibernate.archive.autodetection" value="class,hbm"/>
<!--配置Hibernate方言 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<!--配置数据库url -->
<property name="hibernate.connection.url" value="jdbc:oracle:thin:@168.1.50.20:1522:orcl"/>
<!--配置数据库驱动 -->
<property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/>
<!--配置数据库用户名 -->
<property name="hibernate.connection.username" value="scott"/>
<!--配置数据库密码 -->
<property name="hibernate.connection.password" value="scott"/>
<!--设置外连接抓取树的最大深度 -->
<!--<property name="hibernate.max_fetch_depth" value="3"/>-->
<!--自动输出schema创建DDL语句 -->
<!--<property name="hibernate.hbm2ddl.auto" value="update"/>-->
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
运行示例可看到,没有一个sql语句实现了数据的插入和查询,这就是JPA,由于JPA是一种规范,我们可以使用不同的实现,
那么代码中的
Persistence.createEntityManagerFactory("myJPA")
是如何找到具体的实现呢,跟踪
Persistence 便可得到:它是通过java的service load机制获取到具体的实现的,
解压查看hibernate的jar包,可以找到META-INF/services/javax.persistence.spi.PersistenceProvider 文件,这里指定的实现为
org.hibernate.jpa.HibernatePersistenceProvider
这样Persistence就反射实例化此类从而得到一个Persistence提供者,那么如果类路径里有多个实现的jar呢?查看Persistence代码可知,它只会使用第一个。