首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Seam学习(5) 实体管理工厂

2012-09-08 
Seam学习(五)实体管理工厂实体管理器工厂(EntityManagerFactory)通过上一节讲述,可以看到实体管理器工厂 E

Seam学习(五) 实体管理工厂
  实体管理器工厂(EntityManagerFactory)

  通过上一节讲述,可以看到实体管理器工厂 EntityManagerFactory是获得实体管理器EntityManager对象的入口,而EntityManagerFactory对象是通过javax.persistenc.Persistence类中的静态方法createEntityManagerFactory来创建的。

例如下面代码所示。

EntityManagerFactory emf =

javax.persistence.Persistence.createEntityManagerFactory("jpaUnit");

EntityManager em = emf.createEntityManager();

下面首先详细了解一下javax.persistenc.Persistence类中的API。

11.2.1  javax.persistenc.Persistence API
javax.persistenc.Persistence类提供了两个手动创建EntityManagerFactory对象的方法,它们的定义如下所示。

package javax.persistence;

import java.util.*;

public class Persistence {

    /**

    * 指定持久化单元,创建EntityManagerFactory对象

    * @param persistenceUnitName 持久化单元的名称

    */

    public static EntityManagerFactory createEntityManagerFactory(

    String persistenceUnitName) {...}

    /**

    *指定持久化单元和实现者的属性配置,创建EntityManagerFactory对象

    *

    * @param persistenceUnitName持久化单元的名称

    * @param 实现者的属性配置,这些配置将覆盖persistence.xml文件中的配置

    */

    public static EntityManagerFactory createEntityManagerFactory(

    String persistenceUnitName, Map properties) {...}

}

其中,createEntityManagerFactory(String persistenceUnitName, Map properties)方法中properties的参数将覆盖persistence.xml文件配置的参数。

例如persistence.xml中的<property>元素中的配置如下所示。

<?xml version="1.0" encoding="UTF-8"?>

<persistence>

    <persistence-unit name="jpaUnit" transaction-type="RESOURCE_LOCAL">

        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <properties>子

            <property name = "hibernate.connection.driver_class" value = "com.mysql. jdbc.Dr iver"/>

            <property name = "hibernate.connection.url" value = "jdbc:mysql: //localhost:3306/jp ademo"/>

            <property name = "hibernate.connection.username" value = "root"/>

        </properties>

        <property name="hibernate.show_sql" value="true" />

    </persistence-unit>

</persistence>

其中,属性 hibernate.show_sql的值为true,若创建EntityManagerFactory对象时采用以下的代码,则实际获得的 EntityManagerFactory对象属性hibernate.show_sql则为false,即为代码中所设置的将覆盖配置文件中所配置的,如下所示。

Map properties = new HashMap();

properties.put("hibernate.show_sql", "false");

EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaUnit", properties);

11.2.2  EntityManagerFactory API
上一节创建了EntityManagerFactory对象,那么如何使用EntityManagerFactory对象创建EntityManager对象呢?下面来看EntityManagerFactory的定义,如下所示。

public interface javax.persistence.EntityManagerFactory {

    /**

    * 创建EntityManager对象,每次都创建一个新EntityManager对象

    * 创建后EntityManager对象处于打开状态,isOpen()为true

    */

    public EntityManager createEntityManager();

    /**

    * 自定义配置属性创建EntityManager对象,

    * 每次都创建一个新EntityManager对象

    * 创建后EntityManagerFactory对象处于打开状态,isOpen()为true

    */

    public EntityManager createEntityManager(Map map);

    /**

    * 关闭EntityManagerFactory对象,并且释放相关的资源

    * 如果在关闭了EntityManagerFactory对象后,

    * 调用相关的方法将抛IllegalStateException异常

    * 一但关闭了EntityManagerFactory对象,所有创建的EntityManager对象也将关闭

    */

    public void close();

    /**

    * 判断EntityManagerFactory对象是否已打开

    * 若打开返回true,关闭返回false

    */

    public boolean isOpen();

}

在创建EntityManagerFactory对象后,使用完后应该及时关闭。所以使用创建Entity ManagerFactory的代码如下所示。

EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaUnit");

EntityManager entityManager = emf.createEntityManager();

/**CRUD操作*/

entityManager.close();

emf.close();

11.2.3  实现自己的JPA
细心的读者可能会有疑问,为什么如下的简单代码就可以创建名称为“jpaUnit”的EntityManagerFactory对象呢?

EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaUnit");

虽然这部分内容在使用JPA时并不需要了解,但如果读者想要自己实现JPA规范,这些内容是必须要了解的。

下面以笔者自己实现的简单例子,详细讲述其中的原理。通过这个完整的例子,读者可以对JPA的实现有更深刻的理解。

11.2.3.1  实现PersistenceProvider接口
首先编写一个类JPAPersistence并实现javax.persistence.spi.PersistenceProvider类,代码如下所示。

package com.fengmanfei.jpa;

import java.util.Map;

import javax.persistence.EntityManagerFactory;

import javax.persistence.spi.PersistenceProvider;

import javax.persistence.spi.PersistenceUnitInfo;

public class JPAPersistence implements PersistenceProvider {

    /**接口中的方法*/

    public EntityManagerFactory createContainerEntityManagerFactory(

            PersistenceUnitInfo persistenceunitinfo, Map map) {

        /** 初始化EntityManagerFactory */

        System.out.println(this.getClass().getName()

                + ".createContainerEntityManagerFactory"

                + "(PersistenceUnitInfo persistenceunitinfo,Map map)自己实现的方法");

        return new EntityManagerFactoryImpl();

    }

    /**接口中的方法*/

    public EntityManagerFactory createEntityManagerFactory(String s, Map map) {

        /** 初始化EntityManagerFactory */

        System.out.println(this.getClass().getName()

                + ".createContainerEntityManagerFactory"

                + "(String s, Map map)自己实现的方法");

        return new EntityManagerFactoryImpl();

    }

}

由于这里只是简单地说明如何初始化JPA的实现,所以只打印出调用方法的信息,并返回EntityManagerFactoryImpl对象。

11.2.3.2  实现EntityManagerFactory接口
然后编写一个简单的实现EntityManagerFactory接口的类EntityManagerFactoryImpl,代码如下所示。

package com.fengmanfei.jpa;

import java.util.Map;

import javax.persistence.EntityManager;

import javax.persistence.EntityManagerFactory;

public class EntityManagerFactoryImpl implements EntityManagerFactory {

    public void close() {

        /**自己的实现*/

    }

    public EntityManager createEntityManager() {

        /**自己的实现*/

        return null;

    }

    public EntityManager createEntityManager(Map map) {

        /**自己的实现*/

        return null;

    }

    public boolean isOpen() {

        /**自己的实现*/

        return false;

    }

}

其中,这里接口中的方法笔者并没有编写自己的实现,读者如果需要可以自己添加代码。对于这里所实现的 javax.persistence.spi.PersistenceProvide类所在的包,可以通过JPA的官方网站下载,也可以从 “JBOSS_HOME\server\default\lib”目录下的ejb3-persistence.jar包中获得,在编译时要将这个类包添加到构建路径中。

11.2.3.3  定义自己的实现类
在META-INF文件目录下创建services\javax.persistence.spi.PersistenceProvider文件,在该文件中输入实现PersistenceProvider接口类的全名,如下所示。

com.fengmanfei.jpa.JPAPersistence


修改persistence.xml中的配置如下所示。

<?xml version="1.0" encoding="UTF-8"?>

<persistence >

    <persistence-unit name="jpaUnit"

        transaction-type="RESOURCE_LOCAL">

        <provider>com.fengmanfei.jpa.JPAPersistence</provider>

    </persistence-unit>

</persistence>

其中<provider>要配置为所实现的javax.persistence.spi.PersistenceProvider接口类。这样当客户端创建“jpaUnit”EntityManagerFactory对象时,就会调用自己实现的方法。

例如,客户端代码如下所示。

public class CustomerClient {

    public static void main(String[] args) {

        /** 创建EntityManagerFactory对象 */

        EntityManagerFactory emf = Persistence

                .createEntityManagerFactory("jpaUnit");

        /**其他代码省略*/

    }

}

程序运行后,控制台将输出如下所示的运行结果。

com.fengmanfei.jpa.JPAPersistence.createContainerEntityManagerFactory(String s, Map map)自己实现的方法

可以看到,当调用javax.persistenc.Persistence中的createEntityManagerFactory时,运行的是com.fengmanfei.jpa.JPAPersistence中的方法,并输出了相应的结果。

11.2.3.5  加载原理
当调用 javax.persistenc.Persistence中的createEntityManagerFactory方法时,程序会自动查找当前类加载器中所有的META-INF/services/javax.persistence.spi.PersistenceProvider文件中定义的 JPA实现类,如果还未初始化,则首先将这些实现类实例化。如果实现类已经实例化,则根据根据“unitName”来创建对应的实现类,直到返回的 EntityManagerFactory不为null为止。


如果读者想要更深入地了解JPA具体是如何实现的,建议读者研究一下Hibernate的源代码,这是一个很好的学习途径。

热点排行