`
whitesock
  • 浏览: 484451 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

OpenJPA (1)

    博客分类:
  • EE
阅读更多

1 Overview
    Apache OpenJPA是JPA规范的一个实现,它既可以用于POJO的持久层,也可以被集成到EJB3.0兼容的容器中或者其它轻量级的框架中。在Apache Geronimo 2.0 版本中通过OpenEJB使用了OpenJPA。在WebLogic和WebShpere中也采用了OpenJPA。目前OpenJPA的最新版本是1.0.2。在OpenJPA中大量使用了generic和annotation,因此需要使用1.5以上版本的JDK。

    以下是JPA中使用的主要组件:

  • Persistence: javax.persistence.Persistence类包含静态方法用于获得EntityManagerFactory对象。
  • EntityManagerFactory: javax.persistence.EntityManagerFactory类是创建EntityManager的工厂类。
  • EntityManager: javax.persistence.EntityManager是应用中主要使用的接口,它主要用于管理持久对象,也用于创建Query 接口。
  • Entity。Entity用于封装持久对象。
  • EntityTransaction: EntityTransaction 用于封装事务,javax.persistence.EntityTransaction和EntityManager之间是一对一的关系。
  • Query: javax.persistence.Query接口用于持久对象的查询。它支持Java Persistence Query Language (JPQL) 和 Structured Query Language (SQL)。
  • PersistenceException: JPA异常体系的根是PersistenceException,它继承于RuntimeException。OpenJPA中抛出的异常都实现了org.apache.openjpa.util.ExceptionInfo接口,用于提供额外的信息。

   以下是使用JPA的一个例子:

EntityManagerFactory factory = Persistence.createEntityManagerFactory(null);
EntityManager em = factory.createEntityManager(PersistenceContextType.EXTENDED);
EntityTransaction tx = em.getTransaction();
tx.begin();
Query query = em.createQuery("select e from Employee e where e.division.name = 'Research' AND e.avgHours > 40");
List results = query.getResultList ();
for (Object res : results) {
    Employee emp = (Employee) res;
    emp.setSalary(emp.getSalary() * 1.1);
}
tx.commit();
em.close();
factory.close();

 

2 Entity
    JPA 区分两种不同的persistent class: entity classes 和 embeddable classes. EntityManager可以通过persistent identity来查询entity 实例,或者在Query中指定条件来查询entity实例。在另一方面,embedded实例没有persistent identity,也不能直接从EntityManager或者Query的查询中得到。

2.1 Restrictions on Persistent Classes
    在编写persistent class的时候,不需要继承任何父类或者实现任何接口。 但是persistent class需要一个无参构造函数。如果需要的话,OpenJPA的enhancer也可以创建一个protected 无参构造函数,所以当使用enhancer的时候,persistent class可以不提供无参构造函数。OpenJPA支持final classes 和 final methods。
    所有的entity classes必须提供一个或者多个字段来组成一个persistent identity。你可以为persistent class提供一个version字段,用来检测并发修改,这个字段必须是整数型的(例如int,Long)或者是java.sql.Timestamp。version字段应该是不可变(immutable)的。除了version字段以外,OpenJPA也支持通过其它的方式检测并发修改。
    JPA支持persistent class的继承,但是persistent class不能继承自一些包含native实现的系统类,例如:java.net.Socket 和 java.lang.Thread。如果一个persistent class继承自non-persistent class,那么non-persistent class中的字段不能被持久化。具有继承关系的所有类必须有相同的identity type。

2.2 Entity Identity
    Java中有两种判断object identity的方式:使用==操作符判断同一个JVM中两个引用的值是否相等,或者说指向相同对象;使用equals 方法来判断两个对象是否满足定制的相等条件。JPA中引入了另外一种判断object identity的方式,称为entity identity或者 persistent identity。Entity identity被封装到持久对象的identity字段中,如果两个相同类型的entities拥有相同的identity字段,那么这两个entities代表datastore中相同的状态。Identity字段必须是以下类型:primitives、primitive wrappers、 Strings、Dates、Timestamps或者embeddable types。
    当你处理single persistence context的时候,可以不必通过比较identity字段来判断这些entities是否代表datastore中相同的状态,而是可以通过==操作符。JPA要求每一个persistence context中只能保持一个object来代表每一个datastore record,因此entity identity相当于引用相等。

 

2.2.1 Identity Class
    如果entity 中只有一个identity字段,那么可以将这个字段用作所有EntityManager APIs的identity object;否则必须提供一个identity class,它必须符合以下条件:

  • The class must be public.
  • The class must be serializable.
  • The class must have a public no-args constructor.
  • The names of the non-static fields or properties of the class must be the same as the names of the identity fields or properties of the corresponding entity class, and the types must be identical.
  • The equals and hashCode methods of the class must use the values of all fields or properties corresponding to identity fields or properties in the entity class.
  • If the class is an inner class, it must be static.
  • All entity classes related by inheritance must use the same identity class, or else each entity class must have its own identity class whose inheritance hierarchy mirrors the inheritance hierarchy of the owning entity classes.

   以下是个使用多个identity字段的entity class的例子:

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;

@Entity
@IdClass(Magazine.MagazineId.class)
public class Magazine {
	@Id
	private String isbn;
	
	@Id
	private String title;

	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("isbn: " + isbn);
		sb.append(", title: " + title);
		return sb.toString();
	}
	
	public String getIsbn() {
		return isbn;
	}

	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}
	
	public static class MagazineId {
		// each identity field in the Magazine class must have a
        // corresponding field in the identity class
		private String isbn;
		private String title;
		
		public MagazineId() {
		}
		
		public MagazineId(String isbn, String title) {
			this.isbn = isbn;
			this.title = title;
		}
		
		/**
         * Equality must be implemented in terms of identity field
         * equality, and must use instanceof rather than comparing 
         * classes directly (some JPA implementations may subclass the
         * identity class).
         */
		public boolean equals(Object obj) {
			if(this == obj) {
				return true;
			}
			if(!(obj instanceof MagazineId)) {
				return false;
			}
			
			MagazineId rhs = (MagazineId)obj;
			boolean b1 = (isbn == rhs.isbn || (isbn != null && isbn.equals(rhs.isbn)));
			boolean b2 = (title == rhs.title || (title != null && title.equals(rhs.title)));
			return b1 && b2;
		}
		
		/**
         * Hashcode must also depend on identity values.
         */
		public int hashCode(){
			int h1 = (isbn == null ? 0 : isbn.hashCode());
			int h2 = (title == null ? 0 : title.hashCode());
			return h1 ^ h2;
		}
		
		public String toString() {
			StringBuffer sb = new StringBuffer();
			sb.append("isbn: " + isbn);
			sb.append(", title: " + title);
			return sb.toString();
		}
	}
}

   除了手工编写Id class之外,也可以通过ApplicationIdTool自动生成Id class,例如:

   java org.apache.openjpa.enhance.ApplicationIdTool -s Id Magazine.java
    关于其可选的命令行参数,请参考Apache OpenJPA的user guide。
    如果觉得在命令行上执行命令比较麻烦,也可以在程序里直接调用其main方法,如下:

String suffix = "Id";
String java = "./src/com/example/entity/Product.java";
ApplicationIdTool.main(new String[]{"-d", "./src/", "-s", suffix, java});

   关于如何在类的继承体系中编写identity class,请参考Apache OpenJPA的user guide。

 

2.3 Lifecycle Callbacks
    经常需要在persistent object 生命周期的不同阶段实施不用的动作。JPA包含了多种不同的callback 方法来监控persistent object。这些callback方法可以在persistent classes 中定义,也可以在non-persistent listener classes 中定义。

2.3.1 Callback Methods
    每一个persistence event都有相关的callback方法标记,如下:

  • PrePersist: 用这个annotation 标记的方法会在对象被持久化之前调用。这个方法可以用来为持久化对象设置主键。
  • PostPersist: 用这个annotation 标记的方法会在对象被持久化之后调用。这个方法可以用来在model被保存后更新view。
  • PostLoad: 用这个annotation 标记的方法会在对象中所有eagerly fetched 字段被加载后调用。这个方法通常用来根据加载后的持久化字段的值更初始化非持久字段的值。
  • PreUpdate: 用这个annotation 标记的方法会在对象中持久字段的值被flush到datastore前被调用。 这个方法通常用来根据非持久字段的值来设置持久字段。
  • PostUpdate: 用这个annotation 标记的方法会在对象中持久字段值的改变被保存到datastore后调用。这个方法可以用来清空应用层的过期数据。
  • PreRemove: 用这个annotation 标记的方法会在对象经事务标记成已删除状态前调用。在这个方法中访问持久字段是合法的。在这个方法中,可以基于复杂的条件级联删除其它对象,或者做其它的清理工作。
  • PostRemove: 用这个annotation 标记的方法会在对象被标记成已删除状态后调用。

   除了属性存取方法外,任何没有参数的方法都可以用以上annotation标记。一个方法也可以使用多个annotation标记。以下是个persistent classes的例子

/**
 * Example persistent class declaring our entity listener.
 */
@Entity
public class Magazine {

    @Transient 
    private byte[][] data;

    @ManyToMany
    private List<Photo> photos;

    @PostLoad
    public void convertPhotos() {
        data = new byte[photos.size()][];
        for (int i = 0; i < photos.size(); i++)
            data[i] = photos.get(i).toByteArray();
    }

    @PreDelete
    public void logMagazineDeletion() {
        getLog().debug("deleting magazine containing" + photos.size() 
            + " photos.");
    }
}

   也可以使用XML文件,如下:  

<entity class="Magazine">
    <pre-remove>logMagazineDeletion</pre-remove>
    <post-load>convertPhotos</post-load>
</entity>

 

2.3.2 Entity Listeners
    在persistent classes 中加入Lifecycle Callbacks并不总是理想,更优雅的方式是在 non-persistent listener class 中处理生命周期内的相关事件。Entity listener classes需要有一个无参的构造函数,callback 方法需要有个java.lang.Object 型的参数来指定激发事件的持久对象。Entities可以通过EntityListeners这个annotation来枚举listeners。以下是个Entity和Entity Listener的例子:

/**
 * Example persistent class declaring our entity listener.
 */
@Entity
@EntityListeners({ MagazineLogger.class, ... })
public class Magazine {

    // ... //
}


/**
 * Example entity listener.
 */
public class MagazineLogger {

    @PostPersist
    public void logAddition(Object pc) {
        getLog ().debug ("Added new magazine:" + ((Magazine) pc).getTitle ());
    }


    @PreRemove
    public void logDeletion(Object pc) {
        getLog().debug("Removing from circulation:" + 
            ((Magazine) pc).getTitle());
    }
}

   也可以在XML文件中定义Entity Listeners,如下: 

<entity class="Magazine">
    <entity-listeners>
        <entity-listener class="MagazineLogger">
            <post-persist>logAddition</post-persist>
            <pre-remove>logDeletion</pre-remove>
        </entity-listener>
    </entity-listeners>
</entity>

   关于entity listeners的调用顺序,默认listener会最先被调用;接下来,父类的listeners会先调用,然后是子类的listeners;最后,如果entity上还有某个事件的多个callback方法,那么会按照这些callback方法在entity上声明顺序来调用。

   可以使用以下两个class-level的annotation,以便在entity listeners的调用链上去掉默认listener和父类中定义的listener:

  • ExcludeDefaultListeners: 这个annotation 表明这个类及其子类上不再调用默认listeners。
  • ExcludeSuperclassListeners: 这个annotation 指示OpenJPA不调用父类上声明的任何entity listeners。
17
2
分享到:
评论

相关推荐

    openjpa 写的一个例子

    1. **环境配置**:确保你的开发环境已经安装了Java SDK、Web服务器(如Tomcat)、Maven或Gradle等构建工具,以及OpenJPA依赖库。 2. **项目结构**:一个典型的Web应用项目应包含`WEB-INF`目录,其中包含`web.xml`...

    openjpa范例及实例工程

    默认情况下,当应用程序第一次获取实体标识时,OpenJPA 框架从数据库中一次性获取 50 个连续的实体标识缓存起来,当下一次应用程序需要获取实体标识时,OpenJPA 将首先检测缓存中是否存在实体标识,如果存在,Open...

    OpenJPA 2.2.1 API (CHM格式)

    OpenJPA  OpenJPA 是 Apache 组织提供的开源项目,它实现了 EJB 3.0 中的 JPA 标准,为开发者提供功能强大、使用简单的持久化数据管理框架。OpenJPA 封装了和关系型数据库交互的操作,让开发者把注意力集中在编写...

    openjpa 源码 下载 帮助开发人员调试

    1. **对象关系映射(ORM)**:OpenJPA将Java对象模型与数据库表之间的映射关系进行管理,使得开发者可以使用面向对象的方式处理数据,无需关心底层的SQL语句。 2. **实体管理**:OpenJPA提供了Entity Manager,它是...

    Spring和openJPA集成

    1. **配置OpenJPA** 首先,需要在项目的pom.xml文件中添加OpenJPA和Spring的依赖。然后,在Spring的配置文件(如applicationContext.xml)中声明OpenJPA的数据源、实体管理和事务管理器。 2. **实体类定义** ...

    Open JPA2 employee 简单例子

    OpenJPA2是一个开源的对象关系映射(ORM)框架,它是Java Persistence API(JPA)规范的实现。在这个“Open JPA2 employee简单例子”中,我们将深入理解如何使用OpenJPA2来处理数据库中的员工数据。这个示例将帮助...

    Spring中使用OpenJPA

    1. **添加依赖**:在你的项目中,你需要添加Spring和OpenJPA的库依赖。在Maven的`pom.xml`文件中,你需要添加如下依赖: ```xml &lt;groupId&gt;org.springframework &lt;artifactId&gt;spring-context &lt;version&gt;5.x.x....

    openJpa的应用,感觉还可以

    1. **配置OpenJPA**:这通常涉及到在应用程序的配置文件(如persistence.xml)中设置数据源、实体管理工厂、缓存策略等参数。 2. **实体类设计**:学习如何使用Java注解(如@Entity、@Table、@Id等)来定义数据库表...

    jsf、openJpa学习

    **JSF与OpenJPA整合** 涉及到在JSF应用中使用OpenJPA进行数据访问。这通常包括配置OpenJPA的数据源、实体管理器工厂,以及在JSF Managed Beans中注入实体管理器,以便在处理用户请求时执行CRUD操作。JSF的事件驱动...

    openjpa jar

    1. **实体管理**:OpenJPA支持定义实体类,这些类代表数据库中的表,通过注解或XML配置文件来描述实体与表之间的映射关系。实体类的实例可以通过EntityManager进行管理,包括创建、查询、更新和删除。 2. **查询...

    openJPA官方手册

    ### OpenJPA官方手册知识点概览 #### 一、引言 - **OpenJPA**:作为Apache项目的一部分,OpenJPA是一个开源的Java持久化框架(Java Persistence Framework),它支持Java Persistence API (JPA) 的规范。OpenJPA...

    通过 WebSphere Application Server V6.1 利用 OpenJPA

    安装OpenJPA的步骤通常包括下载OpenJPA的jar文件,将其添加到服务器的类路径中,并在服务器配置中指定OpenJPA作为默认的持久化提供者。 接下来,我们需要创建一个JPA项目。这涉及定义实体类,这些类代表数据库中的...

    Spring MVC+OpenJPA框架

    Spring MVC和OpenJPA是Java开发中常用的两个框架,它们分别在Web应用和持久层处理上发挥着重要作用。Spring MVC是Spring框架的一部分,用于构建高效、灵活的Web应用程序,而OpenJPA则是一个实现了Java Persistence ...

    OpenJPA API 文档 chm格式

    OpenJPA API 文档 chm格式

    Apache OpenJPA 2.1 User's Guide

    ### Apache OpenJPA 2.1 用户指南:Java Persistence API 的深入解析 #### 一、简介 Apache OpenJPA 2.1 是基于 Sun Microsystems 的 Java Persistence 2.0 API (JSR-317 JPA 2.0) 规范实现的一种透明持久化 Java ...

    openjpa:Apache OpenJPA

    Apache OpenJPA-自述文件 前言 感谢您下载此版本的Apache OpenJPA。 Apache OpenJPA是Java Persistence API规范的实现。 执照 此存储库的内容已根据Apache License 2.0 许可 更多信息 可以在openjpa-project子目录...

    openjpa-manual

    ### OpenJPA-Manual 关键知识点解析 #### 一、OpenJPA介绍 **1.1 关于本文档** 本文档旨在提供一个全面且深入的指南,帮助开发人员理解和掌握Java Persistence API(JPA)的核心概念及其在Apache OpenJPA中的实现...

    Openjpa2.2+Mysql+Maven+Servlet+JSP source code

    Openjpa2.2+Mysql+Maven+Servlet+JSP 博客源码: http://blog.csdn.net/shenhonglei1234/article/details/10394379

    apache-openjpa-2.2.1-binary

    1. **对象关系映射(ORM)**:OpenJPA允许开发者使用Java类来表示数据库表,并通过注解或XML配置文件定义这些类与数据库表之间的映射关系。这样,开发者可以像操作普通Java对象一样操作数据库记录。 2. **懒加载...

Global site tag (gtag.js) - Google Analytics