JPA

Posted 大圣

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JPA相关的知识,希望对你有一定的参考价值。

一、 简介
  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路径下。

以上是关于JPA的主要内容,如果未能解决你的问题,请参考以下文章

带有 JPA/EJB 代码的“分离实体传递给持久错误”

Glassfish - 无法使用 JPA 删除实体

从数据库为 JPA 实体生成自定义代码

JPA 之 QueryDSL-JPA 使用指南

您将如何使 JPA 2.1 模块独立于 JPA 实现?

在每个模型的不同 DAL 类中实现 JPA 存储库方法时如何避免重复的代码行/代码块