- 浏览: 483788 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
龘龘龘:
TrueBrian 写道有个问题,Sample 1中,为了控制 ...
What's New on Java 7 Phaser -
龘龘龘:
楼主总结的不错。
What's New on Java 7 Phaser -
TrueBrian:
有个问题,Sample 1中,为了控制线程的启动时机,博主实际 ...
What's New on Java 7 Phaser -
liguanqun811:
不知道楼主是否对zookeeper实现的分布式锁进行过性能测试 ...
Distributed Lock -
hobitton:
mysql的get lock有版本限制,否则get lock可 ...
Distributed Lock
10 Miscellaneous Features
10.1 Restoring State
JPA规范要求不应该使用rolled back objects,但是这些对象在OpenJPA中是有效的。可以通过配置openjpa.RestoreState 属性来控制是否将对象的状态回滚到事务前的状态。它有以下可选值:
- none: 不回滚对象状态,但是对象变成hollow,在下次访问的时候会重新加载。
- immutable: 回滚不可变的状态,可变的状态变成hollow,在下次访问的时候会重新加载。
- all: 回滚所有状态。
10.2 Typing and Ordering
当为对象的属性加载persistent state的时候,OpenJPA会检查这个属性在声明时或者无参构造函数中被赋值的类型。如果这个类型比声明的类型更精确,那么OpenJPA会用这个类型。如果你在初始化某个属性的时候使用了comparator,那么OpenJPA也会在每次加载persistent state的时候使用这个comparator。例如:
public class Company { // OpenJPA 会在每次加载数据的时候使用SalaryComparator。 private Collection employeesBySal = new TreeSet(new SalaryComparator()); private Map departments; public Company { // OpenJPA会使用TreeMap来保存departments 相关的persistent state。 departments = new TreeMap(); } }
10.3 Proxies
10.3.1 Smart Proxies
在运行时,OpenJPA可以通过代理跟踪entity 实例的属性是否被修改过,以便更有效地更新数据库。当设计persistent class的时候,应该尽可能将collection field映射成java.util.Set、java.util.TreeSet或java.util.HashSet。Smart proxy对这些类型可以进行更好的优化。
10.3.2 Large Result Set Proxies
当遍历persistent collection 或者map属性的时候,ORM的缺省行为是把所有persistent state载入到内存中。然而,如果载入的数据量过大,那么可能会降低性能。OpenJPA为这些large result set属性使用特殊的代理。它并不在内存中缓存任何数据,相反它会访问数据库来获得相关的结果。例如large result set collection的contains方法会导致在数据库中执行类似于SELECT COUNT(*) WHERE的查询。类似地,在每次试图获得iterator的时候,OpenJPA会使用当前的large result set配置来执行特定的query。在调用iterator.next方法的时候,OpenJPA会按需载入结果对象。此时需要通过OpenJPAPersistence.close方法来释放资源,例如:
import org.apache.openjpa.persistence.*; @Entity public class Company { @ManyToMany @LRS private Collection<Employee> employees; ... } Collection employees = company.getEmployees(); // employees is a lrs collection Iterator itr = employees.iterator(); while (itr.hasNext()) { process((Employee) itr.next()); } OpenJPAPersistence.close(itr);
Large result set 属性只能被声明成java.util.Collection 或者java.util.Map;它不能包含externalizer;Large result set proxy不能从一个entity 实例转移到另外一个entity 实例中,例如以下代码会导致提交时的一个错误:
Collection employees = company.getEmployees() // employees is a lrs collection company.setEmployees(null); anotherCompany.setEmployees(employees);
10.3.3 Custom Proxies
OpenJPA通过org.apache.openjpa.util.ProxyManager接口管理代理。其缺省的实现是org.apache.openjpa.util.ProxyManagerImpl。它有以下配置属性:
- TrackChanges: 是否使用smart proxy,缺省是true。
- AssertAllowedType: 在向collection或map中加入元素的时候,如果跟metadata 中声明的类型不符,是否抛出异常,缺省是false。
以下是个简单的例子:
<property name="openjpa.ProxyManager" value="TrackChanges=false"/>
缺省的proxy manager可以代理 Collection, List, Map, Queue, Date, or Calendar 等类上的标准方法,也可以代理定制类型,但是这些定制类型必须复合以下条件:
- Custom container types必须有一个公共的无参构造函数,或者一个公共的以Comparator为参数类型的构造函数。
- Custom date types必须有一个公共的无参构造函数,或者一个公共的以long为参数 类型(代表当前的时间)的构造函数。
- Other custom types必须有一个公共的无参构造函数,或者公共的拷贝构造函数。如果没有公共的拷贝构造函数,那么在进行拷贝的时候,首先会创建一个对象B,然后通过以A上getter方法的返回值为参数,调用B的setter方法。 因此你要确保通过这种方式,B是A的完整拷贝。
如果某个custom classes无法满足以上条件,那么OpenJPA允许你定义你自己的proxy class和proxy manager。
10.4 Externalization
OpenJPA 支持通过custom field mappings 来完全控制entity class的field在datastore中怎样被保存、查询和加载。然而一个更轻量级的方法是使用externalization 。Externalization 支持通过指定某些方法来控制保存和加载的方式。需要注意的是,不能在@EmbeddedId字段上使用externalization。
OpenJPA使用org.apache.openjpa.persistence.Externalizer annotation指定将某个属性转换为external value的方法名。如果指定一个non-static方法,那么OpenJPA会假定目标对象是被Externalizer标记的属性对象;如果指定一个static方法, 那么被OpenJPA会把被Externalizer标记的属性对象作为一个方法的参数。每个方法也可以接受一个StoreContext 型的参数。方法的返回值指定了缺省的external 类型。假设希望将某个CustomType类型的属性转换成String类型,那么可以采用以下的方法:
Method | Extension |
public String CustomType.toString() | @Externalizer("toString") |
public String CustomType.toString(StoreContext ctx) | @Externalizer("toString") |
public static String AnyClass.toString(CustomType ct) | @Externalizer("AnyClass.toString") |
public static String AnyClass.toString(CustomType ct, StoreContext ctx) | @Externalizer("AnyClass.toString") |
OpenJPA使用org.apache.openjpa.persistence.Factory annotation指定根据external value初始化某个属性的方法名。 如果指定static方法,那么这个方法必须返回这个属性类型的一个实例。这个方法可以接受StoreContext 类型的一个参数。如果没有指定factory annotation,那么这个属性的class必须包含以external form为参数的构造函数,否则会抛出一个异常。假设希望将String类型转换成某个CustomType类型,那么可以采用以下的方法:
Method | Extension |
public CustomType(String str) | none |
public static CustomType CustomType.fromString(String str) | @Factory("fromString") |
public static CustomType CustomType.fromString(String str, StoreContext ctx) | @Factory("fromString") |
public static CustomType AnyClass.fromString(String str) | @Factory("AnyClass.fromString") |
public static CustomType AnyClass.fromString(String str, StoreContext ctx) | @Factory("AnyClass.fromString") |
OpenJPA使用org.apache.openjpa.persistence.ExternalValues annotation指定external value的转换。 其value pairs用于指定Java和datastore的类型。如果datastore的类型不同于Java类型,那么通过org.apache.openjpa.persistence.Type annotation 指定datastore类型。如果externalized属性不是标准的persistent type,那么必须用org.apache.openjpa.persistence.Persistent annotation显式地进行标记。如果externalized 属性是可变的,而且不是collection、map和date类型,那么OpenJPA无法进行脏检查。可以手动进行标记为dirty,或者使用custom field proxy。以下是个简单的例子:
@Entity public class Externalization { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Persistent @Externalizer("getName") @Factory("forName") private Class clazz; @Persistent @Factory("Externalization.stringToURL") @Externalizer("Externalization.urlToString") private URL url; @Basic @ExternalValues({"SMALL=5", "MEDIUM=8", "LARGE=10"}) @Type(int.class) private String size; public static URL stringToURL(String s) { try { return new URL(s); } catch (MalformedURLException e) { throw new RuntimeException(e); } } public static String urlToString(URL url) { return url.toExternalForm(); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("id: ").append(id); sb.append(", clazz: ").append(clazz); sb.append(", url: ").append(url); sb.append(", size: ").append(size); return sb.toString(); } } EntityManager em = entityManagerFactory.createEntityManager(); em.getTransaction().begin(); Externalization e1 = new Externalization(); e1.setClazz(Externalization.class); e1.setUrl(new URL("http://www.abc.com")); e1.setSize("MEDIUM"); em.persist(e1); em.getTransaction().commit(); em.close(); em = entityManagerFactory.createEntityManager(); Query q = em.createQuery("select m from Externalization m where m.url = 'http://www.abc.com'"); List<Externalization> r1 = (List<Externalization>)q.getResultList(); for(Iterator iter = r1.iterator(); iter.hasNext(); ) { System.out.println(iter.next().toString()); } em.close();
以上代码执行完毕后数据库中externalization表的数据如下:
mysql> select * from externalization; +----+-----------------+------+--------------------+ | id | clazz | size | url | +----+-----------------+------+--------------------+ | 1 | Externalization | 8 | http://www.abc.com | +----+-----------------+------+--------------------+
10.5 Fetch Groups
Fetch groups是一组同时被加载的属性。之前介绍的Fetch Type指定了如何通过annotations指定某个属性是eagerly还是 lazily 加载。Fetch groups 则是提供了动态指定加载方式的能力。.
10.5.1 Custom Fetch Groups
OpenJPA缺省fetch group中的属性都会被eagerly加载。此外可以通过org.apache.openjpa.persistence.FetchGroup annotation定义named fetch groups以便在运行时激活它。在加载的时候,OpenJPA会eagerly加载所有被激活的fetch groups中的属性。FetchGroup annotation有以下属性:
- String name: fetch group 的全局名。以下名字被OpenJPA保留:default 、values、 all、none以及任何以jdo、jpa或openjpa开头的名字。
- FetchAttribute[] attributes: fetch group中persistent fileds或者properties数组。
- String[] fetchGroups: 包含在次fetch group中的其它fetch groups名。
org.apache.openjpa.persistence.FetchAttribute annotation的属性如下:
- String name: persistent field 或者 property 名。
- recursionDepth: eager-fetch 的递归深度,缺省是1(-1无限制)。
Entity class的某个属性可以包含在任何的fetch group中,它也可以声明其load fetch group。缺省情况下,OpenJPA在第一次访问lazy-loaded属性的时候访问数据库。然而如果你直到当你访问某个lazy-loaded属性A的时候,你很可能也同时访问lazy-loaded 属性B和C,因此在一次数据库访问中同时加载A、B和C是更有效的。
通过org.apache.openjpa.persistence.LoadFetchGroup annotation为某个属性指定load fetch group。以下是个简单的例子:
import org.apache.openjpa.persistence.*; @Entity @FetchGroups({ @FetchGroup(name="detail", attributes={ @FetchAttribute(name="publisher"), @FetchAttribute(name="articles") }) }) public class Magazine { @ManyToOne(fetch=FetchType.LAZY) @LoadFetchGroup("detail") private Publisher publisher; }
10.5.2 Custom Fetch Group Configuration
OpenJPAEntityManager接口和OpenJPAQuery接口可以用于访问org.apache.openjpa.persistence.FetchPlan。FetchPlan通过以下方法维护当前活跃的fetch groups和maximum fetch depth:
public FetchPlan addFetchGroup(String group); public FetchPlan addFetchGroups(String... groups); public FetchPlan addFetchGroups(Collection groups); public FetchPlan removeFetchGrop(String group); public FetchPlan removeFetchGroups(String... groups); public FetchPlan removeFetchGroups(Collection groups); public FetchPlan resetFetchGroups(); public Collection<String> getFetchGroups(); public void clearFetchGroups(); public FetchPlan setMaxFetchDepth(int depth); public int getMaxFetchDepth();
Maximum fetch depth指定了加载时遍历对象的深度,缺省值是-1(无限制)。如果MaxFetchDepth是1,那么OpenJPA将会加载目标实例和它的直接relations; 如果MaxFetchDepth是2,那么OpenJPA会加载目标实例、直接relations和直接relations上的relations;如果MaxFetchDepth是-1,那么OpenJPA会加载目标实例以及所有的relatons直到到达对象图的边缘。当然以上的加载过程依赖于被加载属性是否是eagerly load,以及当前活跃的fetch group。以下是个简单的例子:
OpenJPAQuery kq = OpenJPAPersistence.cast(em.createQuery(...)); kq.getFetchPlan().setMaxFetchDepth(3).addFetchGroup("detail"); List results = kq.getResultList();
10.5.3 Per-field Fetch Configuration
除了基于per-fetch-group 的配置外,OpenJPA也支持基于per-field的配置。通过以下方法将特定的field包含到当前的fetch plan中。
public FetchPlan addField(String field); public FetchPlan addFields(String... fields); public FetchPlan addFields(Class cls, String... fields); public FetchPlan addFields(Collection fields); public FetchPlan addFields(Class cls, Collection fields); public FetchPlan removeField(String field); public FetchPlan removeFields(String... fields); public FetchPlan removeFields(Class cls, String... fields); public FetchPlan removeFields(Collection fields); public FetchPlan removeFields(Class cls, Collection fields); public Collection<String> getFields(); public void clearFields();
需要注意的是,以上方法中的field必须定义在指定的类中,而不是在其父类中。如果field publisher被定义在Publication中,而不是其子类Magazine中,那么必须用 addField (Publication.class, "publisher"),而不是addField (Magazine.class, "publisher")。出于性能上的考虑,OpenJPA并不对class name / field name 对进行验证。如果指定了不存在的class name / field name 对,那么会被OpenJPA忽略。以下是个简单的例子:
OpenJPAEntityManager kem = OpenJPAPersistence.cast(em); kem.getFetchPlan().addField(Magazine.class, "publisher"); Magazine mag = em.find(Magazine.class, magId);
发表评论
-
Terracotta in Action (3)
2009-03-25 09:20 51503 Inside Terracotta 3.1 Core T ... -
Terracotta in Action (2)
2009-03-21 21:09 47152. Terracotta Eclipse Plugin ... -
Terracotta in Action (1)
2009-03-19 21:52 62941. Introduction Terraco ... -
OpenEJB (4)
2008-05-11 09:05 3192本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenEJB (3)
2008-05-11 09:04 2733本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenEJB (2)
2008-05-11 09:03 3326本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenEJB (1)
2008-05-10 22:39 5111本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenJPA (6)
2008-03-23 21:33 63618 Object Locking 8.1 Configu ... -
OpenJPA (5)
2008-03-18 22:38 50627 Inheritance 对象使用引用以便关联到其 ... -
OpenJPA (4)
2008-03-11 23:27 71226 Query 6.1 JPQL Queries 6.1. ... -
OpenJPA (3)
2008-03-09 23:09 52714 EntityManagerFactory 4.1 Ove ... -
OpenJPA (2)
2008-03-05 23:59 73033 Metadata 通过javax.persist ... -
OpenJPA (1)
2008-03-04 23:11 68911 Overview Apache OpenJPA是 ... -
ActiveMQ in Action (7)
2008-02-27 14:33 126832.6.7 Wildcards Wil ... -
ActiveMQ in Action (6)
2008-02-26 15:22 138072.6 Features ActiveMQ包含了很多 ... -
ActiveMQ in Action (5)
2008-02-26 00:35 136122.5 Clustering ActiveMQ从多种 ... -
ActiveMQ in Action (4)
2008-02-26 00:21 112942.4 Security ActiveMQ ... -
ActiveMQ in Action (3)
2008-02-26 00:16 106422.3 Persistence 2.3.1 AMQ Mess ... -
ActiveMQ in Action (2)
2008-02-25 23:58 132982.2 Transport ActiveMQ目前支持 ... -
ActiveMQ in Action (1)
2008-02-25 23:18 238971 JMS 在介绍ActiveMQ ...
相关推荐
7. **部署和测试**:将打包好的Web应用部署到Web服务器上,通过浏览器进行测试,查看OpenJPA是否能正常存取数据。 在"openjpademo"这个例子中,你可以期待看到如何设置和配置这些组件的详细步骤,以及如何编写相关...
默认情况下,当应用程序第一次获取实体标识时,OpenJPA 框架从数据库中一次性获取 50 个连续的实体标识缓存起来,当下一次应用程序需要获取实体标识时,OpenJPA 将首先检测缓存中是否存在实体标识,如果存在,Open...
OpenJPA OpenJPA 是 Apache 组织提供的开源项目,它实现了 EJB 3.0 中的 JPA 标准,为开发者提供功能强大、使用简单的持久化数据管理框架。OpenJPA 封装了和关系型数据库交互的操作,让开发者把注意力集中在编写...
OpenJPA,全称Open Java Persistence API,是Apache软件基金会的一个开源项目,它实现了Java持久化API(Java Persistence API,JPA),为Java开发者提供了一种标准的方式来管理和持久化应用程序中的对象。...
**Spring和OpenJPA集成详解** 在Java世界中,Spring框架和OpenJPA(Open Java Persistence)是两个非常重要的组件。Spring作为一个全面的轻量级应用框架,提供了大量的功能,包括依赖注入、AOP(面向切面编程)、...
OpenJPA2是一个开源的对象关系映射(ORM)框架,它是Java Persistence API(JPA)规范的实现。在这个“Open JPA2 employee简单例子”中,我们将深入理解如何使用OpenJPA2来处理数据库中的员工数据。这个示例将帮助...
OpenJPA(Java Persistence API)则是Java平台上的一个ORM(对象关系映射)工具,它实现了JSR-317规范,使得开发者可以方便地在Java应用程序中操作数据库。本篇将详细讲解如何在Spring项目中集成并使用OpenJPA。 ...
OpenJPA(Open Java Persistence API)是Apache软件基金会下的一个开源项目,它是Java持久层标准JPA(Java Persistence API)的一个实现。JPA是Java EE平台中的一个重要组件,用于管理和处理应用程序中的对象-关系...
**JSF与OpenJPA整合** 涉及到在JSF应用中使用OpenJPA进行数据访问。这通常包括配置OpenJPA的数据源、实体管理器工厂,以及在JSF Managed Beans中注入实体管理器,以便在处理用户请求时执行CRUD操作。JSF的事件驱动...
7. **插件扩展性**:Apache OpenJPA的设计使其具有高度的可扩展性,允许开发者通过插件自定义和扩展其行为,例如自定义查询解析器、持久化提供者等。 8. **数据库支持**:OpenJPA支持多种数据库,包括Oracle、MySQL...
### OpenJPA官方手册知识点概览 #### 一、引言 - **OpenJPA**:作为Apache项目的一部分,OpenJPA是一个开源的Java持久化框架(Java Persistence Framework),它支持Java Persistence API (JPA) 的规范。OpenJPA...
安装OpenJPA的步骤通常包括下载OpenJPA的jar文件,将其添加到服务器的类路径中,并在服务器配置中指定OpenJPA作为默认的持久化提供者。 接下来,我们需要创建一个JPA项目。这涉及定义实体类,这些类代表数据库中的...
Spring MVC和OpenJPA是Java开发中常用的两个框架,它们分别在Web应用和持久层处理上发挥着重要作用。Spring MVC是Spring框架的一部分,用于构建高效、灵活的Web应用程序,而OpenJPA则是一个实现了Java Persistence ...
OpenJPA API 文档 chm格式
### Apache OpenJPA 2.1 用户指南:Java Persistence API 的深入解析 #### 一、简介 Apache OpenJPA 2.1 是基于 Sun Microsystems 的 Java Persistence 2.0 API (JSR-317 JPA 2.0) 规范实现的一种透明持久化 Java ...
Apache OpenJPA-自述文件 前言 感谢您下载此版本的Apache OpenJPA。 Apache OpenJPA是Java Persistence API规范的实现。 执照 此存储库的内容已根据Apache License 2.0 许可 更多信息 可以在openjpa-project子目录...
### OpenJPA-Manual 关键知识点解析 #### 一、OpenJPA介绍 **1.1 关于本文档** 本文档旨在提供一个全面且深入的指南,帮助开发人员理解和掌握Java Persistence API(JPA)的核心概念及其在Apache OpenJPA中的实现...
Openjpa2.2+Mysql+Maven+Servlet+JSP 博客源码: http://blog.csdn.net/shenhonglei1234/article/details/10394379
7. **插件式架构**:OpenJPA的架构允许用户自定义策略和实现,以便适应不同的持久化需求和环境。 8. **兼容性**:Apache OpenJPA与多种Java应用服务器和数据库系统兼容,包括Tomcat、WebLogic、JBOSS、Oracle、...