一、 简介
1.JPA规范本质上就是一种ORM规范,它制定了一些规范,提供了一些编程的API接口,具体实现由应用服务器厂商来提供,JBoss应用服务器底层就以Hibernate作为JPA实现。也就是说,基于JPA基础的具体JPA实现可以包括 Hibernate,TopLink以及其他ORM框架。
2.JPA规范虽然与EJB3规范一同出现,但是JPA规范并不属于EJB3规范,它是一套完全独立的规范。JPA不仅可以在基于EJB的JavaEE中使用,而且可以在普通Java SE中使用。
3.JPA中最常用的3种组件:
实体:就是一个普通的POJO,可以通过orm.xml映射文件或者Annotation建立实体与底层数据表之间的对应关系
EntityManager:实体没有任何持久化能力,需要使用EntityManager操作实体,作用类似于Hibernate中的Session
JPQL查询:类似于Hibernate中的HQL查询语言。JPA提供了一个Query接口来执行查询。
二 、具体应用
1.实体
@Entity @Table(name="product") public class ProductType { private Integer typeid; @Id @GeneratedValue(strategy=GenerationType.AUTO) public Integer getTypeid() { return typeid; } public void setTypeid(Integer typeid) { this.typeid = typeid; } }
@Entity和@Table的区别:
@Entity说明这个class是实体类,并且使用默认的orm规则,即class名即数据库表中表名,class字段名即表中的字段名
如果想改变这种默认的orm规则,就要使用@Table来改变class名与数据库中表名的映射规则,
@Column来改变class中字段名与db中表的字段名的映射规则,不过在mybatis中,可以通过驼峰映射标签进行自动映射。
在进行实际的数据库访问之前,Hibernate需要使用hibernate.cfg.xml文件管理数据库连接、连接池信息,JPA需要使用persistence.xml来进行管理。不管是哪种JPA实现,persistence.xml文件总是在放在类加载路径的META-INF路径下。
2.persistence.xml
首先下载hibernate,解压,将hibernate3.jar(Hibernate核心jar包),lib路径下的required目录和jpa目录下的所有jar包添加到应用的类加载路径中。
以下是一个简单的persistence.xml文件
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" version="2.1"> <persistence-unit name="itcast" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>com.itcast.bean.product.ProductType</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" /> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> <property name="hibernate.connection.url" value="jdbc:mysql:///mydb" /> <property name="hibernate.connection.username" value="root" /> <property name="hibernate.connection.password" value="123456" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="show_sql" value="true" /> <property name="hibernate.format_sql" value="false" /> </properties> </persistence-unit> </persistence>
persistence.xml文件通过<persistence-unit>元素配置持久化单元,其中name指定持久化单元名称,transaction-type指定事务类型,支持以下两个属性值:
JTA:使用JTA全局事务,这是默认值,指定该值后还需要使用<jta-data-resource>元素指定容器管理的XA数据源
RESOURCE_LOCAL:使用局部事务,JavaSE程序通常采用局部事务
<persistence-unit>中还包含3个子元素:
(1)<provider>:指定JPA实现的提供类,在应用服务器环境中无须指定该元素
(2)<class>,<mapping-file>,<jar-file>:用于指定实体,其中<class>指定实体类的类名,<mapping-file>指定实体类的映射文件,<jar-file>指定实体类所在的JAR包。
(3)<properties>:可以包含多个<property>子元素,用于为特定JPA实现配置对应的属性。
除此之外,如果希望让JPA使用容器管理的数据源,则应该在<persistence-unit>元素内添加<jta-data-resource>子元素,该子元素的内容就是JTA数据源的JNDI名称。
其他一些配置:
<property name="hibernate.ejb.cfgfile" value=".../../hibernate.cfg.xml" /> 如果程序已经在hibernate.cfg.xml文件中指定了数据库的相关信息,则可以在persistence.xml中指定hibernate.cfg.xml的位置即可 hibernate.max_fetch_depth:设置关联实体的最大抓取深度,0表示不抓取实体,建议在0-3之间,默认为1
hibernate.default_batch_fetch_size:设置加载关联实体集时所加载的关联实体的个数,建议使用2的倍数。
3.EntityManager
JPA的核心API就是EntityManager,EntityManager负责管理JPA持久化上下文中的所有实体,在程序中使用EntityManager大致有三种情况:
(1)在EJB中使用:直接使用依赖注入进行管理
(2)在Servlet,JSF的托管Bean中使用:不能直接使用依赖注入,因为多个请求线程可能共享同一个Servlet或JSF的托管Bean,而EntityManager并没有被设计成线程安全的,因此可能会导致线程安全问题。这个问题有两种解决方法:使用JNDI查找来获得EntityManager对象;使用依赖注入管理EntityManagerFactory对象,再通过EntityManagerFactory来获取EntityManager对象
(3)在Java SE应用中使用:需要应用程序显式的创建EntityManager,过程如下:
通过javax.persistence.Persistence工厂类提供的createEntityManagerFactory()静态方法创建EntityManagerFactory对象,调用该方法时需要传入persistence.xml文件中持久化单元的名称。
调用EntityManagerFactory的createEntityManager()或createEntityManager(Map map)方法来创建EntityManager对象。如果传入了一个Map参数,那么这个Map参数传入的属性会补充或覆盖persistence.xml文件中配置的属性。
这里可以将EntityManager类比为Hibernate中的Session,EntityManagerFactory类比为Hibernate中的SessionFactory
具体使用:
1 public class ProductTest { 2 private static final EntityManagerFactory=Persistence.createEntityManagerFactory("itcast"); 3 public static void main(String[] args){ 4 final EntityManager em=factory.createEntityManager(); 5 ProductType product =new ProductType(); 6 try{ 7 em.getTransaction().begin(); 8 em.persist(product); 9 em.getTransaction().commit(); 10 }finally{ 11 em.close(); 12 } 13 } 14 }
4.EntityManager包含了大量方法来对实体执行保存、删除和检索等操作,常用的一些方法如下:
void persist(Object entity):持久化实体到数据库
T merge(T entity):将指定实体合并到数据库
void remove(T entity)
void detach(Object entity):将指定实体从缓存中清除
T find(Class<T> entityClass,Object pk):根据主体的主键加载实体
T getReference(Class<T> entityClass,Object pk):根据主体的主键加载实体,有延迟加载的功能
void setFlushMode(FlushModeType flushMode):设置持久化上下文的flush模式,该模式可以是AUTO(EntityManager自动管理实体和数据库的同步)或COMMIT
void flush():将持久化上下文中的实体状态同步到数据库
void refresh(Object entity):刷新指定实体状态
Query createQuery(String sql):根据指定JPQL语句创建查询
Query createNamedQuery(String name):根据配置中的查询名创建命名查询
Query createNativeQuery(String sqlString):根据指定SQL语句创建原生的SQL查询
void close()
boolean isOpen():判断EntityManager是否打开
JPA除了用Annotation来管理实体和数据表之间的对应关系外,还可以使用orm.xml文件来进行管理,就像Hibernate使用*.hbm.xml文件一样。
一旦为实体提供了orm.xml映射文件,就要在persistence.xml中使用<mapping-file>元素来加载该映射文件。
注意:persistence.xml文件必须位于META-INF路径下,包含META-INF路径的路径或JAR包被称为持久化单元的根,持久化单元的作用域由持久化单元的根确定。主要包括以下三种情况:
对于一个Java SE应用程序而言,如果程序没有将persistence.xml文件打成JAR包,则应该将该文件放在应用类加载路径的META-INF路径下;
如果将persistence.xml文件打包到某个EJB JAR包中,则应该将persistence.xml文件放在该EJB JAR包的META-INF路径下;
如果将persistence.xml打包成某个Web应用的JAR包,则将persistence.xml放在该WAR的WEB-INF/classes/META-INF路径下;对于不打包成WAR包的Web应用,也应该将persistence.xml文件放在Web应用的WEB-INF/classes/META-INF路径下。