blob: f0cfb114763e4963ba174f84189e8d1bb217670d [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>6.&nbsp; Persistent Fields</title><base href="display"><link rel="stylesheet" type="text/css" href="css/docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="manual.html" title="Apache OpenJPA 2.3 User's Guide"><link rel="up" href="ref_guide_pc.html" title="Chapter&nbsp;5.&nbsp; Persistent Classes"><link rel="prev" href="ref_guide_inverses.html" title="5.&nbsp; Managed Inverses"><link rel="next" href="ref_guide_fetch.html" title="7.&nbsp; Fetch Groups"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6.&nbsp;
Persistent Fields
</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ref_guide_inverses.html">Prev</a>&nbsp;</td><th width="60%" align="center">Chapter&nbsp;5.&nbsp;
Persistent Classes
</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="ref_guide_fetch.html">Next</a></td></tr></table><hr></div><div class="section" title="6.&nbsp; Persistent Fields"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="ref_guide_pc_scos">6.&nbsp;
Persistent Fields
</h2></div></div></div><div class="toc"><dl><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_restore">6.1.
Restoring State
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_order">6.2.
Typing and Ordering
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_calendar_timezone">6.3.
Calendar Fields and TimeZones
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy">6.4.
Proxies
</a></span></dt><dd><dl><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_smart">6.4.1.
Smart Proxies
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_lrs">6.4.2.
Large Result Set Proxies
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_custom">6.4.3.
Custom Proxies
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_serial">6.4.4.
Serialization
</a></span></dt></dl></dd><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_extern">6.5.
Externalization
</a></span></dt><dd><dl><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_extern_values">6.5.1.
External Values
</a></span></dt></dl></dd></dl></div>
<a class="indexterm" name="d5e12402"></a>
<p>
OpenJPA enhances the specification's support for persistent fields in many ways.
This section documents aspects of OpenJPA's persistent field handling that may
affect the way you design your persistent classes.
</p>
<div class="section" title="6.1.&nbsp; Restoring State"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_scos_restore">6.1.&nbsp;
Restoring State
</h3></div></div></div>
<a class="indexterm" name="d5e12407"></a>
<a class="indexterm" name="d5e12410"></a>
<p>
While the JPA specification says that you should not use rolled back objects,
such objects are perfectly valid in OpenJPA. You can control whether the
objects' managed state is rolled back to its pre-transaction values with the
<a class="link" href="ref_guide_conf_openjpa.html#openjpa.RestoreState" title="5.62.&nbsp; openjpa.RestoreState"><code class="literal">openjpa.RestoreState</code>
</a> configuration property. <code class="literal">none</code> does not roll back state
(the object becomes hollow, and will re-load its state the next time it is
accessed), <code class="literal">immutable</code> restores immutable values (primitives,
primitive wrappers, strings) and clears mutable values so that they are reloaded
on next access, and <code class="literal">all</code> restores all managed values to their
pre-transaction state.
</p>
</div>
<div class="section" title="6.2.&nbsp; Typing and Ordering"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_scos_order">6.2.&nbsp;
Typing and Ordering
</h3></div></div></div>
<a class="indexterm" name="d5e12420"></a>
<p>
When loading data into a field, OpenJPA examines the value you assign the field
in your declaration code or in your no-args constructor. If the field value's
type is more specific than the field's declared type, OpenJPA uses the value
type to hold the loaded data. OpenJPA also uses the comparator you've
initialized the field with, if any. Therefore, you can use custom comparators on
your persistent field simply by setting up the comparator and using it in your
field's initial value.
</p>
<div class="example"><a name="ref_guide_pc_scos_order_initialvals"></a><p class="title"><b>Example&nbsp;5.12.&nbsp;
Using Initial Field Values
</b></p><div class="example-contents">
<p>
Though the annotations are left out for simplicity, assume <code class="literal">
employeesBySal</code> and <code class="literal">departments</code> are persistent
fields in the class below.
</p>
<pre class="programlisting">
public class Company {
// OpenJPA will detect the custom comparator in the initial field value
// and use it whenever loading data from the database into this field
private Collection employeesBySal = new TreeSet(new SalaryComparator());
private Map departments;
public Company {
// or we can initialize fields in our no-args constructor; even though
// this field is declared type Map, OpenJPA will detect that it's
// actually a TreeMap and use natural ordering for loaded data
departments = new TreeMap();
}
// rest of class definition...
}
</pre>
</div></div><br class="example-break">
</div>
<div class="section" title="6.3.&nbsp; Calendar Fields and TimeZones"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_calendar_timezone">6.3.&nbsp;
Calendar Fields and TimeZones
</h3></div></div></div>
<a class="indexterm" name="d5e12432"></a>
<p>
OpenJPA's support for the <code class="classname">java.util.Calendar</code> type will
store only the <code class="classname">Date</code> part of the field, not the
<code class="classname">TimeZone</code> associated with the field. When loading the date
into the <code class="classname">Calendar</code> field, OpenJPA will use the <code class="classname">
TimeZone</code> that was used to initialize the field.
</p>
</div>
<div class="section" title="6.4.&nbsp; Proxies"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_scos_proxy">6.4.&nbsp;
Proxies
</h3></div></div></div><div class="toc"><dl><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_smart">6.4.1.
Smart Proxies
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_lrs">6.4.2.
Large Result Set Proxies
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_custom">6.4.3.
Custom Proxies
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_serial">6.4.4.
Serialization
</a></span></dt></dl></div>
<a class="indexterm" name="d5e12443"></a>
<a class="indexterm" name="d5e12445"></a>
<p>
At runtime, the values of all mutable second class object fields in persistent
and transactional objects are replaced with implementation-specific proxies. On
modification, these proxies notify their owning instance that they have been
changed, so that the appropriate updates can be made on the datastore.
</p>
<div class="section" title="6.4.1.&nbsp; Smart Proxies"><div class="titlepage"><div><div><h4 class="title" id="ref_guide_pc_scos_proxy_smart">6.4.1.&nbsp;
Smart Proxies
</h4></div></div></div>
<a class="indexterm" name="d5e12452"></a>
<p>
Most proxies only track whether or not they have been modified. Smart proxies
for collection and map fields, however, keep a record of which elements have
been added, removed, and changed. This record enables the OpenJPA runtime to
make more efficient database updates on these fields.
</p>
<p>
When designing your persistent classes, keep in mind that you can optimize for
OpenJPA smart proxies by using fields of type <code class="classname">java.util.Set
</code>, <code class="classname">java.util.TreeSet</code>, and <code class="classname">
java.util.HashSet</code> for your collections whenever possible. Smart
proxies for these types are more efficient than proxies for <code class="classname">
List</code>s. You can also design your own smart proxies to further
optimize OpenJPA for your usage patterns. See the section on
<a class="link" href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_custom" title="6.4.3.&nbsp; Custom Proxies">custom proxies</a> for
details.
</p>
</div>
<div class="section" title="6.4.2.&nbsp; Large Result Set Proxies"><div class="titlepage"><div><div><h4 class="title" id="ref_guide_pc_scos_proxy_lrs">6.4.2.&nbsp;
Large Result Set Proxies
</h4></div></div></div>
<a class="indexterm" name="d5e12464"></a>
<a class="indexterm" name="d5e12467"></a>
<p>
Under standard ORM behavior, traversing a persistent collection or map field
brings the entire contents of that field into memory. Some persistent fields,
however, might represent huge amounts of data, to the point that attempting to
fully instantiate them can overwhelm the JVM or seriously degrade performance.
</p>
<p>
OpenJPA uses special proxy types to represent these "large result set" fields.
OpenJPA's large result set proxies do not cache any data in memory. Instead,
each operation on the proxy offloads the work to the database and returns the
proper result. For example, the <code class="methodname">contains</code> method of a
large result set collection will perform a <code class="literal"> SELECT COUNT(*)</code>
query with the proper <code class="literal">WHERE</code> conditions to find out if the
given element exists in the database's record of the collection. Similarly, each
time you obtain an iterator OpenJPA performs the proper query using the current
<a class="link" href="ref_guide_dbsetup_lrs.html" title="10.&nbsp; Large Result Sets">large result set settings</a>, as
discussed in the <a class="link" href="ref_guide_dbsetup.html" title="Chapter&nbsp;4.&nbsp; JDBC">JDBC</a> chapter. As you
invoke <code class="methodname">Iterator.next</code>, OpenJPA instantiates the result
objects on-demand.
</p>
<p>
You can free the resources used by a large result set iterator by passing it to
the static <a class="link" href="ref_guide_runtime_jpa.html#ref_guide_runtime_openjpapersistence" title="2.9.&nbsp; OpenJPAPersistence"><code class="methodname">
OpenJPAPersistence.close</code></a> method.
</p>
<div class="example"><a name="ref_guide_pc_scos_proxy_lrs_itr"></a><p class="title"><b>Example&nbsp;5.13.&nbsp;
Using a Large Result Set Iterator
</b></p><div class="example-contents">
<pre class="programlisting">
import org.apache.openjpa.persistence.*;
...
Collection employees = company.getEmployees(); // employees is a lrs collection
Iterator itr = employees.iterator();
while (itr.hasNext())
process((Employee) itr.next());
OpenJPAPersistence.close(itr);
</pre>
</div></div><br class="example-break">
<p>
You can also add and remove from large result set proxies, just as with standard
fields. OpenJPA keeps a record of all changes to the elements of the proxy,
which it uses to make sure the proper results are always returned from
collection and map methods, and to update the field's database record on commit.
</p>
<p>
In order to use large result set proxies in JPA, add the
<a class="ulink" href="../javadoc/org/apache/openjpa/persistence/LRS.html" target="_top"><code class="classname">
org.apache.openjpa.persistence.LRS</code></a> annotation to the
persistent field.
</p>
<p>
The following restrictions apply to large result set fields:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
<p>
The field must be declared as either a <code class="classname">java.util.Collection
</code> or <code class="classname">java.util.Map</code>. It cannot be declared as
any other type, including any sub-interface of collection or map, or any
concrete collection or map class.
</p>
</li><li class="listitem">
<p>
The field cannot have an externalizer (see
<a class="xref" href="ref_guide_pc_scos.html#ref_guide_pc_extern" title="6.5.&nbsp; Externalization">Section&nbsp;6.5, &#8220;
Externalization
&#8221;</a>).
</p>
</li><li class="listitem">
<p>
Because they rely on their owning object for context, large result set proxies
cannot be transferred from one persistent field to another. The following code
would result in an error on commit:
</p>
<pre class="programlisting">
Collection employees = company.getEmployees() // employees is a lrs collection
company.setEmployees(null);
anotherCompany.setEmployees(employees);
</pre>
</li></ul></div>
<div class="example"><a name="ref_guide_pc_scos_proxy_lrs_extension"></a><p class="title"><b>Example&nbsp;5.14.&nbsp;
Marking a Large Result Set Field
</b></p><div class="example-contents">
<pre class="programlisting">
import org.apache.openjpa.persistence.*;
@Entity
public class Company {
@ManyToMany
@LRS private Collection&lt;Employee&gt; employees;
...
}
</pre>
</div></div><br class="example-break">
</div>
<div class="section" title="6.4.3.&nbsp; Custom Proxies"><div class="titlepage"><div><div><h4 class="title" id="ref_guide_pc_scos_proxy_custom">6.4.3.&nbsp;
Custom Proxies
</h4></div></div></div>
<a class="indexterm" name="d5e12505"></a>
<a class="indexterm" name="d5e12508"></a>
<p>
OpenJPA manages proxies through the
<a class="ulink" href="../javadoc/org/apache/openjpa/util/ProxyManager.html" target="_top"><code class="classname">
org.apache.openjpa.util.ProxyManager</code></a> interface. OpenJPA
includes a default proxy manager, the <code class="classname">
org.apache.openjpa.util.ProxyManagerImpl</code> (with a plugin alias name
of <code class="literal">default</code>), that will meet the needs of most users. The
default proxy manager understands the following configuration properties:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
<p>
<code class="literal">TrackChanges</code>: Whether to use
<a class="link" href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy_smart" title="6.4.1.&nbsp; Smart Proxies">smart proxies</a>. Defaults to
<code class="literal">true</code>.
</p>
</li><li class="listitem">
<p>
<code class="literal">AssertAllowedType</code>: Whether to immediately throw an exception
if you attempt to add an element to a collection or map that is not assignable
to the element type declared in metadata. Defaults to <code class="literal">false</code>.
</p>
</li><li class="listitem">
<p>
<code class="literal">DelayCollectionLoading</code>: Whether to delay loading elements of a
lazily loaded collection. Delay loading allows non-indexed add and remove
operations to occur without prior loading of the collection from the data store. This can
improve performance of some applications by allowing them to perform simple add or remove
operations on collections without requiring them to be loaded. Delayed proxies are
loaded when an operation is performed that requires loading, such
as iteration, size, serialization, and indexOf. They can also be loaded by casting the
proxy to a <a class="ulink" href="../javadoc/org/apache/openjpa/util/DelayedProxy.html" target="_top"><code class="classname">
org.apache.openjpa.util.DelayedProxy</code></a> and invoking the
<code class="methodname">load</code> method. If a broker factory is available after detaching the owning
entity, a collection may be available for delayed loading after the persistence context has been
cleared. In post-detachment, entities that are loaded are not associated with a persistence context.
Defaults to <code class="literal">false</code>.
</p>
</li></ul></div>
<p>
The default proxy manager can proxy the standard methods of any
<code class="classname">Collection</code>, <code class="classname">List</code>,
<code class="classname">Map</code>, <code class="classname">Queue</code>,
<code class="classname">Date</code>, or <code class="classname">Calendar</code> class,
including custom implementations. It can also proxy custom classes whose
accessor and mutator methods follow JavaBean naming conventions. Your custom
types must, however, meet the following criteria:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
<p>
Custom container types must have a public no-arg constructor or a public
constructor that takes a single <code class="classname">Comparator</code> parameter.
</p>
</li><li class="listitem">
<p>
Custom date types must have a public no-arg constructor or a public
constructor that takes a single <code class="classname">long</code> parameter
representing the current time.
</p>
</li><li class="listitem">
<p>
Other custom types must have a public no-arg constructor or a public copy
constructor. If a custom types does not have a copy constructor, it must be
possible to fully copy an instance A by creating a new instance B and calling
each of B's setters with the value from the corresponding getter on A.
</p>
</li></ul></div>
<p>
If you have custom classes that must be proxied and do not meet these
requirements, OpenJPA allows you to define your own proxy classes and
your own proxy manager. See the <code class="literal">openjpa.util</code> package
<a class="ulink" href="../javadoc/" target="_top">Javadoc</a> for details on the interfaces involved,
and the utility classes OpenJPA provides to assist you.
</p>
<p>
You can plug your custom proxy manager into the OpenJPA runtime through the
<a class="link" href="ref_guide_conf_openjpa.html#openjpa.ProxyManager" title="5.56.&nbsp; openjpa.ProxyManager"><code class="literal"> openjpa.ProxyManager</code>
</a> configuration property.
</p>
<div class="example"><a name="ref_guide_pc_scos_proxy_custom_ex"></a><p class="title"><b>Example&nbsp;5.15.&nbsp;
Configuring the Proxy Manager
</b></p><div class="example-contents">
<pre class="programlisting">
&lt;property name="openjpa.ProxyManager" value="TrackChanges=false"/&gt;
</pre>
</div></div><br class="example-break">
</div>
<div class="section" title="6.4.4.&nbsp; Serialization"><div class="titlepage"><div><div><h4 class="title" id="ref_guide_pc_scos_proxy_serial">6.4.4.&nbsp;
Serialization
</h4></div></div></div>
<a class="indexterm" name="d5e12560"></a>
<a class="indexterm" name="d5e12563"></a>
<p>
When objects are serialized, the <code class="literal">DetachedStateField</code> in
section <a class="xref" href="ref_guide_remote.html#ref_guide_detach_state" title="1.3.1.&nbsp; Detached State">Section&nbsp;1.3.1, &#8220;
Detached State
&#8221;</a>
will be used to help determine when build time proxies will be removed.
If runtime created proxies are being used (proxies not supplied by OpenJPA)
or if an entity has already been detached, then any found proxies will be
removed during serialization.
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
<p>
<code class="literal">transient</code>: Use a transient detached state field. This gives
the benefits of a detached state field to local objects that are never
serialized, but retains serialization compatibility for client tiers without
access to the enhanced versions of your classes or the OpenJPA runtime.
All proxies will be removed during serialization. This is the default.
</p>
</li><li class="listitem">
<p>
<code class="literal">true</code>: Use a non-transient detached state field so that
objects crossing serialization barriers can still be attached efficiently. This
requires, however, that your client tier have the enhanced versions of your
classes and the OpenJPA runtime.
No OpenJPA provided proxies will be removed during serialization.
</p>
</li><li class="listitem">
<p>
<code class="literal">false</code>: Do not use a detached state field.
All proxies will be removed during serialization.
</p>
</li></ul></div>
</div>
</div>
<div class="section" title="6.5.&nbsp; Externalization"><div class="titlepage"><div><div><h3 class="title" id="ref_guide_pc_extern">6.5.&nbsp;
Externalization
</h3></div></div></div><div class="toc"><dl><dt><span class="section"><a href="ref_guide_pc_scos.html#ref_guide_pc_extern_values">6.5.1.
External Values
</a></span></dt></dl></div>
<a class="indexterm" name="d5e12581"></a>
<a class="indexterm" name="d5e12583"></a>
<p>
OpenJPA offers the ability to write
<a class="link" href="ref_guide_mapping_custom.html#ref_guide_mapping_custom_field" title="10.3.&nbsp; Custom Field Mapping">custom field mappings</a> in
order to have complete control over the mechanism with which fields are stored,
queried, and loaded from the datastore. Often, however, a custom mapping is
overkill. There is often a simple transformation from a Java field value to its
database representation. Thus, OpenJPA provides the externalization service.
Externalization allows you to specify methods that will externalize a field
value to its database equivalent on store and then rebuild the value from its
externalized form on load.
</p>
<div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3>
<p>
Fields of embeddable classes used for <code class="literal">@EmbeddedId</code> values in
JPA cannot have externalizers.
</p>
</div>
<p>
The OpenJPA
<a class="ulink" href="../javadoc/org/apache/openjpa/persistence/Externalizer.html" target="_top">
<code class="classname">org.apache.openjpa.persistence.Externalizer</code></a>
annotation sets the name of a method that will be invoked to convert
the field into its external form for database storage. You can specify either
the name of a non-static method, which will be invoked on the field value, or a
static method, which will be invoked with the field value as a parameter. Each
method can also take an optional
<a class="ulink" href="../javadoc/org/apache/openjpa/kernel/StoreContext.html" target="_top"><code class="classname">
StoreContext</code></a> parameter for access to a persistence context.
The return value of the method is the field's external form. By default, OpenJPA
assumes that all named methods belong to the field value's class (or its
superclasses). You can, however, specify static methods of other classes using
the format <code class="literal">&lt;class-name&gt;.&lt;method-name&gt;</code>.
</p>
<p>
Given a field of type <code class="classname">CustomType</code> that externalizes to a
string, the table below demonstrates several possible externalizer methods and
their corresponding metadata extensions.
</p>
<div class="table"><a name="d5e12600"></a><p class="title"><b>Table&nbsp;5.1.&nbsp;
Externalizer Options
</b></p><div class="table-contents">
<table summary="&#xA; Externalizer Options&#xA; " border="1"><colgroup><col align="left" class="method"><col align="left" class="extension"></colgroup><thead><tr><th align="left">
Method
</th><th align="left">
Extension
</th></tr></thead><tbody><tr><td align="left">
<code class="literal">
public String CustomType.toString()
</code>
</td><td align="left">
<code class="literal">
@Externalizer("toString")
</code>
</td></tr><tr><td align="left">
<code class="literal">
public String CustomType.toString(StoreContext ctx)
</code>
</td><td align="left">
<code class="literal">
@Externalizer("toString")
</code>
</td></tr><tr><td align="left">
<code class="literal">
public static String AnyClass.toString(CustomType ct)
</code>
</td><td align="left">
<code class="literal">
@Externalizer("AnyClass.toString")
</code>
</td></tr><tr><td align="left">
<code class="literal">
public static String AnyClass.toString(CustomType ct, StoreContext ctx)
</code>
</td><td align="left">
<code class="literal">
@Externalizer("AnyClass.toString")
</code>
</td></tr></tbody></table>
</div></div><br class="table-break">
<p>
The OpenJPA
<a class="ulink" href="../javadoc/org/apache/openjpa/persistence/Factory.html" target="_top"><code class="classname">
org.apache.openjpa.persistence.Factory</code></a> annotation
contains the name of a method that will be invoked to instantiate the field from
the external form stored in the database. Specify a static method name. The
method will be invoked with the externalized value and must return an
instance of the field type. The method can also take an optional
<a class="ulink" href="../javadoc/org/apache/openjpa/kernel/StoreContext.html" target="_top"><code class="classname">
StoreContext</code></a> parameter for access to a persistence context.
If a factory is not specified, OpenJPA will use the constructor of the field
type that takes a single argument of the external type, or will throw an
exception if no constructor with that signature exists.
</p>
<p>
Given a field of type <code class="classname">CustomType</code> that externalizes to a
string, the table below demonstrates several possible factory methods and their
corresponding metadata extensions.
</p>
<div class="table"><a name="d5e12637"></a><p class="title"><b>Table&nbsp;5.2.&nbsp;
Factory Options
</b></p><div class="table-contents">
<table summary="&#xA; Factory Options&#xA; " border="1"><colgroup><col align="left" class="method"><col align="left" class="extension"></colgroup><thead><tr><th align="left">
Method
</th><th align="left">
Extension
</th></tr></thead><tbody><tr><td align="left">
<code class="literal">
public CustomType(String str)
</code>
</td><td align="left">
none
</td></tr><tr><td align="left">
<code class="literal">
public static CustomType CustomType.fromString(String str)
</code>
</td><td align="left">
<code class="literal">
@Factory("fromString")
</code>
</td></tr><tr><td align="left">
<code class="literal">
public static CustomType CustomType.fromString(String str, StoreContext ctx)
</code>
</td><td align="left">
<code class="literal">
@Factory("fromString")
</code>
</td></tr><tr><td align="left">
<code class="literal">
public static CustomType AnyClass.fromString(String str)
</code>
</td><td align="left">
<code class="literal">
@Factory("AnyClass.fromString")
</code>
</td></tr><tr><td align="left">
<code class="literal">
public static CustomType AnyClass.fromString(String str, StoreContext ctx)
</code>
</td><td align="left">
<code class="literal">
@Factory("AnyClass.fromString")
</code>
</td></tr></tbody></table>
</div></div><br class="table-break">
<p>
If your externalized field is not a standard persistent type, you must
explicitly mark it persistent. In OpenJPA, you can force a persistent field
by annotating it with <a class="link" href="ref_guide_meta_jpa.html#ref_guide_meta_jpa_persistent" title="3.3.&nbsp; Persistent Field Values"><code class="classname">
org.apache.openjpa.persistence.Persistent</code></a> annotation.
</p>
<div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3>
<p>
If your custom field type is mutable and is not a standard collection, map, or
date class, OpenJPA will not be able to detect changes to the field. You must
mark the field dirty manually, or create a custom field proxy.
See
<a class="ulink" href="../javadoc/org/apache/openjpa/persistence/OpenJPAEntityManager.html" target="_top">
<code class="methodname">OpenJPAEntityManager.dirty</code></a> for how to mark a
field dirty manually in JPA.
See <a class="xref" href="ref_guide_pc_scos.html#ref_guide_pc_scos_proxy" title="6.4.&nbsp; Proxies">Section&nbsp;6.4, &#8220;
Proxies
&#8221;</a> for a discussion of proxies.
</p>
</div>
<p>
You can externalize a field to virtually any value that is supported by
OpenJPA's field mappings (embedded relations are the exception; you must declare
your field to be a persistence-capable type in order to embed it). This means
that a field can externalize to something as simple as a primitive, something as
complex as a collection or map of entities, or anything in
between. If you do choose to externalize to a collection or map, OpenJPA
recognizes a family of metadata extensions for specifying type information for the
externalized form of your fields - see <a class="xref" href="ref_guide_meta_ext.html#type" title="4.2.6.&nbsp; Type">Section&nbsp;4.2.6, &#8220;
Type
&#8221;</a>. If the
external form of your field is an entity object or contains entities, OpenJPA
will correctly include the objects in its persistence-by-reachability
algorithms and its delete-dependent algorithms.
</p>
<p>
The example below demonstrates a few forms of externalization.
</p>
<div class="example"><a name="ref_guide_pc_externex"></a><p class="title"><b>Example&nbsp;5.16.&nbsp;
Using Externalization
</b></p><div class="example-contents">
<pre class="programlisting">
import org.apache.openjpa.persistence.*;
@Entity
public class Magazine {
// use Class.getName and Class.forName to go to/from strings
@Persistent
@Externalizer("getName")
@Factory("forName")
private Class cls;
// use URL.getExternalForm for externalization. no factory;
// we can rely on the URL string constructor
@Persistent
@Externalizer("toExternalForm")
private URL url;
// use our custom methods
@Persistent
@Externalizer("Magazine.authorsFromCustomType")
@Factory("Magazine.authorsToCustomType")
@ElementType(Author.class)
private CustomType customType;
public static Collection authorsFromCustomType(CustomType customType) {
... logic to pack custom type into a list of authors ...
}
public static CustomType authorsToCustomType(Collection authors) {
... logic to create custom type from a collection of authors ...
}
...
}
</pre>
</div></div><br class="example-break">
<p>
<a class="indexterm" name="d5e12686"></a>
You can query externalized fields using parameters. Pass in a value of the field
type when executing the query. OpenJPA will externalize the parameter using the
externalizer method named in your metadata, and compare the externalized
parameter with the value stored in the database. As a shortcut, OpenJPA also
allows you to use parameters or literals of the field's externalized type in
queries, as demonstrated in the example below.
</p>
<div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3>
<p>
Currently, queries are limited to fields that externalize to a primitive,
primitive wrapper, string, or date types, due to constraints on query syntax.
</p>
</div>
<div class="example"><a name="ref_guide_pc_extern_queryex"></a><p class="title"><b>Example&nbsp;5.17.&nbsp;
Querying Externalization Fields
</b></p><div class="example-contents">
<p>
Assume the <code class="classname">Magazine</code> class has the same fields as in the
previous example.
</p>
<pre class="programlisting">
// you can query using parameters
Query q = em.createQuery("select m from Magazine m where m.url = :u");
q.setParameter("u", new URL("http://www.solarmetric.com"));
List results = q.getResultList();
// or as a shortcut, you can use the externalized form directly
q = em.createQuery("select m from Magazine m where m.url = 'http://www.solarmetric.com'");
results = q.getResultList();
</pre>
</div></div><br class="example-break">
<div class="section" title="6.5.1.&nbsp; External Values"><div class="titlepage"><div><div><h4 class="title" id="ref_guide_pc_extern_values">6.5.1.&nbsp;
External Values
</h4></div></div></div>
<a class="indexterm" name="d5e12698"></a>
<p>
Externalization often takes simple constant values and transforms them to
constant values of a different type. An example would be storing a <code class="classname">
boolean</code> field as a <code class="classname">char</code>, where <code class="literal">true
</code> and <code class="literal">false</code> would be stored in the database as
<code class="literal">'T'</code> and <code class="literal">'F'</code> respectively.
</p>
<p>
OpenJPA allows you to define these simple translations in metadata, so that the
field behaves as in <a class="link" href="ref_guide_pc_scos.html#ref_guide_pc_extern" title="6.5.&nbsp; Externalization">full-fledged
externalization</a> without requiring externalizer and factory methods.
External values supports translation of pre-defined simple types (primitives,
primitive wrappers, and Strings), to other pre-defined simple values.
</p>
<p>
Use the OpenJPA
<a class="ulink" href="../javadoc/org/apache/openjpa/persistence/ExternalValues.html" target="_top">
<code class="classname">org.apache.openjpa.persistence.ExternalValues</code></a>
annotation to define external value translations. The values are
defined in a format similar to that of <a class="link" href="ref_guide_conf_plugins.html" title="4.&nbsp; Plugin Configuration">
configuration plugins</a>, except that the value pairs represent Java and
datastore values. To convert the Java boolean values of <code class="literal">true</code>
and <code class="literal">false</code> to the character values <code class="literal">T</code> and
<code class="literal">F</code>, for example, you would use the extension value: <code class="literal">
true=T,false=F</code>.
</p>
<p>
If the type of the datastore value is different from the field's type, use the
<a class="ulink" href="../javadoc/org/apache/openjpa/persistence/Type.html" target="_top">
<code class="classname">org.apache.openjpa.persistence.Type</code></a> annotation
to define the datastore type.
</p>
<div class="example"><a name="externvalues_ex"></a><p class="title"><b>Example&nbsp;5.18.&nbsp;
Using External Values
</b></p><div class="example-contents">
<p>
This example uses external value translation to transform a string field to an
integer in the database.
</p>
<pre class="programlisting">
public class Magazine {
@ExternalValues({"SMALL=5", "MEDIUM=8", "LARGE=10"})
@Type(int.class)
private String sizeWidth;
...
}
</pre>
</div></div><br class="example-break">
</div>
</div>
</div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ref_guide_inverses.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="ref_guide_pc.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="ref_guide_fetch.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5.&nbsp;
Managed Inverses
&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="manual.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;7.&nbsp;
Fetch Groups
</td></tr></table></div></body></html>