一、JPA概述
- JPA的出现
在早期的Java编程中,不同的数据库具有不同的连接方式,
例如ODBC数据源连接、JDBC-ODBC桥连接等,它们使用不同的方式
保存数据。这便给程序开发增加了复杂度。
后来Java官方推出了JDBC规范,所有的数据库都使用JDBC连接并操作数据库。
这时只需要使用Connection、Statement、PreparedStatement、
ResultSet等JDBC对象,操作SQL语句即可。JDBC标准规范了
数据库的连接方式、SQL执行方式以及查询结果的返回方式。
ORM框架的出现,使直接使用Java对象成为可能。
ORM框架将Java对象拆分成SQL语句,并利用JDBC保存进数据库中。
ORM框架简化了Java对象的持久化工作。但是市面上也存在多种
ORM框架,这些框架截然不同,给开发者造成了难度。
于是,Java官方推出了JPA规范。JPA旨在规范ORM框架,
使ORM框架有统一的接口、统一的用法。 - JPA规范
JPA只是一种ORM规范,并没有具体的实现代码,有点类似于Java中的接口。
JPA并不能单独使用,必须指定JPA底层的实现框架。
使用JPA后,程序便不再依赖于某种ORM框架。 - JPA与EJB3
JPA与EJB3.0都是随着JavaEE5规范发布的。EJB3.0是JavaEE5规范中最重要的
部分,是一种业务组件,包括有状态、无状态等。而JPA是可以看做
EJB3的一部分,用户实现数据的持久化工作。JPA可以脱离EJB3单独使用。 - JavaEE容器
Tomcat只是个Servlet容器,只能运行Servlet规范的组件,
例如Servlet、Filter、JSP等,而不能运行JavaEE规范定义的其他组件。
Servlet容器一般称为Web服务器。
EJB3程序属于重量级程序,必须部署到JavaEE容器中。
JavaEE容器内置对JPA与EJB3等JavaEE规范的支持。常见的
JavaEE容器有Red Hat公司的Jboss,Sun公司的GlassFish等。
二、实例:保存Student实体类
- Student代码
实体类使用Java注解来配置。@Entity、@Table、@Id、@GeneratedValue、@Column等。 - StudentServlet添加、列出所有Student
private EntityManagerFactory emFactory;
@Override
public void init() throws ServletException {
if (emFactory == null) {
emFactory = Persistence.createEntityManagerFactory("jpa");
}
}
EntityManager em = emFactory.createEntityManager();
em.getTransaction.begin();
em.persist(student);
em.getTransaction().commit();
em.close();
//
List studentList = em
.createQuery("select s from Student s order by s.id desc ")
.setMaxResults(100)
.getResultList();
em.close();
public void destroy() {
emFactory.close();
} - persistence.xml代码
在JPA中,参数jpa被称为一个持久化单元(Persistence Unit)。
持久化单元是在persistence.xml中配置的。
persistence.xml文件的路径有明确的定义,必须在classpath的META-INF下,
一般为Web根目录的WEB-INF\classes\META-INF\persistence.xml下。
<persistence-unit name="jpa" transaction-type="RESOURCE-LOCAL">
<properties>
<property name="hibernate.connection.driver_class"
value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.url"
value="jdbc:mysql://localhost:3306/jpa?
character-Encoding=UTF-8"/>
<property name="hibernate.connection.username"
value="root"/>
<property name="hibernate.connection.password"
value="admin"/>
<property name="hibernate.hbm2ddl.auto"
value="create-drop"/>
<property name="hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.show_sql"
value="true"/>
<property name="hibernate.format-sql"
value="true"/>
</properties>
</Persistence-unit> - 配置JBoss服务器
1、在MyEclipse中配置JBoss。单击工具栏的“部署”图标,弹出部署对话框。
选择当前项目jpa,单击Add。
2、弹出服务器配置对话框,单击Edit Server Connectors。
3、选择JBoss4.x,选择Enable,选择JBoss的路径,
Server name使用默认的default,单击OK按钮保存设置。
4、在部署对话框中选择刚刚配置的JBoss4.x,
单击Finish按钮完成自动部署。
需要手工将MySQL驱动mysql-connector-java-5.0.5-bin.jar赋值到
C:\jboss-4.2.3.GA\server\default\lib下。 - 运行JPA程序
单击工具栏启动图标旁边的小三角,
在弹出菜单中选择JBoss 4.x | Start命令,启动JBoss服务器。
三、JPA的API
- JPA定义了一系列的API(程序编程接口,Application Programming Interface),
包括实体类的配置、操作实体类的方式等。JPA的API都位于javx.persistence包下。 - 实体类配置
JPA使用Java注解配置实体类,
例如@Table、@Entity、@OneToMany、@ManyToOne、@ManyToMany等。 - 获取EntityManager
JPA中使用javax.persistence.EntityManager操作实体类。
EntityManager通过EntityManagerFactory获取。
EntityManagerFactory可以由Persistence类获取到。
参数jps在persistence.xml中配置。
也可以用Java注解方式,由容器注入EntityManagerFactory。
@PersistenceUnit(unitName="jpa")
private EntityManagerFactory emFactory;
从EntityManagerFactory获取EntityManager:
EntityMananger em = emFactory.createEntityManager();
...
em.close(); - 实体类的状态
跟Hibernate一样,JPA中的实体类也包括几种状态:
临时状态(Transient)、持久化状态(Persistent)、分离状态(Detached)。
临时状态:
对象在保存进数据库之前为临时状态。这时候数据库中没有该对象的信息,
该对象的Id属性也为空。如果没有被持久化,
程序退出时临时状态的对象信息将会丢失。
持久化状态:
对象在保存进数据库后或者从数据库中加载后、并没有脱离Session时
为持久化状态。这时候数据库中有该对象的信息,该对象的id
为数据库中对应记录的主键值。由于还在Session中,持久化状态的
对象可以执行任何有关数据库的操作。
分离状态:
是对象曾经属于持久化状态、但是现在已经离开Session了。虽然分离状态的
对象有di值,有对应的数据库记录,但是已经无法执行有关数据库的操作。 - 持久化persist()
persist()将临时状态的对象保存进数据库。
由于持久化时设计数据库的写入,因此需要用到事务。 - 查找find()与getReference()
find()与getReference()都能查找对象,
用法也基本一致,不同的是当对象不存在时,find会返回null,
而getReference会抛出javax.persistence.EntityNotFoundException异常。 - 保存merge()
merge(Object obj)将修改后的对象保存进数据库。merge时需要用到事务。 - 删除remove()
remove(Object obj)将对象从数据库中删除。remove需要开启事务。 - 刷新refresh()和包含contains()
refresh(Object obj)重新从数据库中读取数据。
contains(Object obj)判断对象是否在数据库中存在,返回true、false。 - 查询createQuery()
createQuery()返回javax.persistence.Query对象。
Query使用JPQL(Java Persistence Query Language)语句进行查询。
JPQL是一种面向对象化的SQL语句,类似于Hibernate的HQL。
查询时可以设置参数。最终JPA会将JPQL转化为SQL执行。
List studentList = em.createQuery(
" select s from Student s where s.name like
:name order by s.id desc ")
.setParameter("name", "%M%")
.setFirstResult(0)
.setMaxResults(100)
.getResultList();
em.close(); - 本地查询createNativeQuery()
createNativeQuery()返回本地查询对象,
它不使用JPQL查询,而使用底层数据库的SQL语句。 - 写入数据库flush()
执行persist()、merge()时,数据并不是立即写入数据库中,而是由JPA缓存起来,
在执行flush()时写入。在事务提交的时候,JPA会自动执行flush()一次性
保存所有数据。如果需要立即将数据写入数据库,可以手工执行flush()。 - 设定写入模式setFlushModel()
默认地,EntityManager的Flush模式为FlushModel.AUTO。
这种模式下,在执行查询前或者事务提交时自动执行flush()。
可以通过setFlushModel(FLushModel f)设置为FlushModel.COMMIT。
设为COMMIT后只有在事务提交时才会执行flush()写入数据库。 - 返回实现者getDelegate()
getDelegate()返回底层实现ORM框架的引用。
不过这样会与底层实现框架的API发生耦合,因而不推荐使用。 - 清楚对象clear()
可以用clear()清除所有被监视的实体类对象,
但是需要注意,clear()之后对实体类所做的修改将会丢失。