blob: fc814b32f0d6755139ce5bee8a26d689674a9875 [file] [log] [blame]
<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- No caching headers -->
<meta http-equiv="cache-control" content="no-cache"/>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="expires" content="-1"/>
<meta name="keywords" content="JDO, Apache, Java, Data, Objects"/>
<meta name="description" content="Apache JDO - Java Data Objects"/>
<title>JDO Attach/Detach</title>
<link rel="icon" type="image/png" href="images/JDOx150.png"/>
<!--
Apache JDO Documentation Template
==================================
This template derived various aspects from Apache Deltaspike template, the Apache ISIS template and the Datanucleus template.
This template uses
* Bootstrap v3.3.7 (https://getbootstrap.com/) for navbar.
* Asciidoctor "foundation" CSS
* Bootswatch "cosmo" theme for Bootstrap (https://bootswatch.com/cosmo).
* Bootstrap TOC plugin v0.4.1 (https://afeld.github.io/bootstrap-toc/) for the table of contents.
* jQuery (necessary for Bootstrap's JavaScript plugins)
* Font-Awesome for some icons used by Asciidoctor
NOTE: tried using Font-Awesome CSS hosted locally but then fails to work!
-->
<link href="css/bootswatch/3.3.7/bootstrap-cosmo.css" rel="stylesheet"/>
<link href="css/bootstrap-toc/0.4.1/bootstrap-toc.min.css" rel="stylesheet"/>
<link href="css/asciidoctor/foundation.css" rel="stylesheet"/>
<link href="css/datanucleus_theme.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="js/bootstrap/3.3.7/bootstrap.min.js"></script>
<script src="js/bootstrap-toc/0.4.1/bootstrap-toc.min.js"></script>
<!-- Coderay syntax formatter -->
<style type="text/css">
/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid currentColor;opacity:.35;padding:0 .5em 0 0}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff !important;background:#000080 !important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:#000080}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:#008080}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:#008080}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:#008080}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
</style>
</head>
<body data-spy="scroll" data-target="#toc">
<!-- Navbar -->
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<!-- Three line menu button for use on mobile screens -->
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- 'style' added to align image with navbar. FIX THIS -->
<a class="navbar-brand" href="https://db.apache.org/jdo/">
<img style="margin-top: -12px;" alt="Brand" width="45.5" height="45.5" src="images/JDOx150.png"/>
</a>
<!-- TODO Any way to abstract the version from Maven? -->
<a class="navbar-brand" href="index.html">Apache JDO</a>
</div>
<!-- Navbar that will collapse on mobile screens -->
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<!-- menu item General -->
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">General<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="why_jdo.html">Why JDO?</a></li>
<li><a href="getting-started.html">Getting Started</a></li>
<li><a href="specifications.html">Specifications</a></li>
<li><a href="tck.html">TCK</a></li>
<li><a href="javadoc.html">API Javadoc</a></li>
<li role="separator" class="divider"></li>
<li><a href="jdo_v_jpa.html">JDO v JPA</a></li>
<li><a href="jdo_v_jpa_api.html">JDO v JPA : API</a></li>
<li><a href="jdo_v_jpa_orm.html">JDO v JPA : ORM</a></li>
<li role="separator" class="divider"></li>
<li><a href="license.html">License</a></li>
<li><a href="impls.html">Implementations</a></li>
<li><a href="jdo_3_0_overview.html">JDO 3.0 Overview</a></li>
<li><a href="references.html">References</a></li>
<li><a href="glossary.html">Glossary</a></li>
</ul>
</li>
<!-- menu item API Usage -->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" style="background-color:#2385c6">API Usage<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="pmf.html">PersistenceManagerFactory</a></li>
<li><a href="pm.html">PersistenceManager</a></li>
<li><a href="transactions.html">Transactions</a></li>
<li><a href="attach_detach.html">Attach-Detach</a></li>
<li><a href="fetchgroups.html">Fetch Plan/Groups</a></li>
<li><a href="state_transition.html">Object States</a></li>
<li><a href="object_retrieval.html">Object Retrieval</a></li>
<li><a href="exceptions.html">Exceptions</a></li>
<li><a href="jdohelper.html">JDO Helper</a></li>
<li role="separator" class="divider"></li>
<li><a href="guides-replication.html">Data Replication</a></li>
</ul>
</li>
<!-- menu item Types & Metadata -->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Types &amp; Metadata<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="class_types.html">Types of Classes</a></li>
<li><a href="field_types.html">Types of Fields</a></li>
<li role="separator" class="divider"></li>
<!-- <li class="dropdown-header">Metadata</li> -->
<li><a href="metadata.html">MetaData</a></li>
<li><a href="annotations.html">Annotations</a></li>
<li><a href="jdo_dtd.html">jdo DTD/XSD</a></li>
<li><a href="orm_dtd.html">orm DTD/XSD</a></li>
<li><a href="jdoquery_dtd.html">jdoquery DTD/XSD</a></li>
<li><a href="jdoconfig_dtd.html">jdoconfig DTD/XSD</a></li>
<li role="separator" class="divider"></li>
<li><a href="enhancement.html">Bytecode Enhancement</a></li>
</ul>
</li>
<!-- menu item Query -->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Query<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="query_api.html">Query API</a></li>
<li role="separator" class="divider"></li>
<li><a href="jdoql.html">JDOQL</a></li>
<li><a href="jdoql_methods.html">Methods</a></li>
<li><a href="jdoql_result.html">Result</a></li>
<li><a href="jdoql_quickref.pdf">Quick Ref PDF</a></li>
<li><a href="jdoql_typed.html">JDOQL Typed API</a></li>
<li role="separator" class="divider"></li>
<li><a href="query_sql.html">SQL</a></li>
</ul>
</li>
<!-- menu item Community -->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Community<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="get-involved.html">Get Involved</a></li>
<li><a href="team-list.html">Project Team</a></li>
<li><a href="mail-lists.html">Mailing Lists</a></li>
<li><a href="faq.html">FAQ</a></li>
</ul>
</li>
<!-- menu item Development -->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Development<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="roadmap.html">RoadMap / TODO</a></li>
<li><a href="downloads.html">Downloads</a></li>
<li><a href="source-code.html">Source Code</a></li>
<li><a href="coding-standards.html">Coding Standards</a></li>
<li><a href="issuetracking.html">Issue Tracking</a></li>
</ul>
</li>
</ul>
<!-- 'style' added to fix height of input box. FIX THIS -->
<form class="navbar-form navbar-left" role="search" id="search-form" action="https://www.google.com/search" method="get" style="padding: 1px 15px;">
<div class="form-group">
<input name="sitesearch" value="db.apache.org/jdo" type="hidden">
<input name="q" type="text" class="form-control" placeholder="Search" style="margin-top: 7px; padding: 1px; border-radius: 5px; height: 30px; vertical-align: middle;">
</div>
</form>
</div>
</div>
</nav>
<div class="container">
<div class="row-fluid">
<div class="col-sm-9">
<!-- <div class="page-title">
<h3>JDO Attach/Detach</h3>
</div>
-->
<div id="doc-content">
<div class="sect1">
<h2 id="JDO_AttachDetach">JDO Attach/Detach</h2>
<div class="sectionbody">
<div class="paragraph">
<p>JDO provides an interface to the persistence of objects.
JDO 1.0 didn&#8217;t provide a way of taking an object that was just persisted and just work on it and update the persisted object later;
the user had to copy the fields manually and copy them back to the persisted object later.
JDO 2.0 introduced a new way of handling this situation, by <strong>detaching</strong> an object from the persistence graph,
allowing it to be worked on in the users application. It could then be <strong>attached</strong> to the persistence graph later.
Please refer to <a href="state_transition.html">Object Lifecycle</a> for where this fits in.
The first thing to do to use a class with this facility is to tag it as "detachable".
This is done by adding the attribute</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;class</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">MyClass</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">detachable</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This acts as an instruction to the <a href="enhancement.html">enhancement process</a> to add methods necessary to utilise the attach/detach process.</p>
</div>
<div class="paragraph">
<p>The following code fragment highlights how to use the attach/detach mechanism</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">Product working_product=<span class="predefined-constant">null</span>;
Transaction tx=pm.currentTransaction();
<span class="keyword">try</span>
{
tx.begin();
Product prod=<span class="keyword">new</span> Product(name,description,price);
pm.makePersistent(prod);
<span class="comment">// Detach the product for use</span>
working_product = (Product)pm.detachCopy(prod);
tx.commit();
}
<span class="keyword">catch</span> (<span class="exception">Exception</span> e)
{
<span class="comment">// Handle the exception</span>
}
<span class="keyword">finally</span>
{
<span class="keyword">if</span> (tx.isActive())
{
tx.rollback();
}
}
<span class="comment">// Work on the detached object in our application</span>
working_product.setPrice(new_price);
...
<span class="comment">// Reattach the updated object</span>
tx = pm.currentTransaction();
<span class="keyword">try</span>
{
tx.begin();
Product attached_product = pm.makePersistent(working_product);
tx.commit();
}
<span class="keyword">catch</span> (<span class="exception">Exception</span> e)
{
<span class="comment">// Handle the exception</span>
}
<span class="keyword">finally</span>
{
<span class="keyword">if</span> (tx.isActive())
{
tx.rollback();
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>So we now don&#8217;t need to do any manual copying of object fields just using a simple call to detach the object, and then attach it again later.
Here are a few things to note with <em>attach/detach</em> :</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Calling <em>detachCopy</em> on an object that is not detachable will return a <strong>transient</strong> instance that is a COPY of the original, so use the COPY thereafter.</p>
</li>
<li>
<p>Calling <em>detachCopy</em> on an object that is detachable will return a <strong>detached</strong> instance that is a COPY of the original, so use this COPY thereafter</p>
</li>
<li>
<p>A <em>detached</em> object retain the id of its datastore entity.
Detached objects should be used where you want to update the objects and attach them later (updating the associated object in the datastore.
If you want to create copies of the objects in the datastore with their own identities you should use <em>makeTransient</em> instead of <em>detachCopy</em>.</p>
</li>
<li>
<p>Calling <em>detachCopy</em> will detach all fields of that object that are in the current <a href="fetchgroups.html">Fetch Group</a> for that class for that <em>PersistenceManager</em>.</p>
</li>
<li>
<p>By default the fields of the object that will be detached are those in the <em>Default Fetch Group</em>.</p>
</li>
<li>
<p>You should choose your <a href="fetchgroups.html">Fetch Group</a> carefully, bearing in mind which object(s) you want to access whilst detached.
Detaching a relation field will detach the related object as well.</p>
</li>
<li>
<p>If you don&#8217;t detach a field of an object, you <span class="underline">cannot</span> access the value for that field while the object is detached.</p>
</li>
<li>
<p>If you don&#8217;t detach a field of an object, you <span class="underline">can</span> update the value for that field while detached, and thereafter you can access the value for that field.</p>
</li>
<li>
<p>Calling <em>makePersistent</em> will return an (attached) copy of the detached object.
It will attach all fields that were originally detached, and will also attach any other fields that were modified whilst detached.</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="detach_all_on_commit">Detach All On Commit</h3>
<div class="paragraph">
<p>JDO also provides a mechanism whereby all objects that were enlisted in a transaction are automatically detached when the transaction is committed.
You can enable this in one of 3 ways.
If you want to use this mode globally for all <em>PersistenceManager</em>s (PMs) from a <em>PersistenceManagerFactory</em> (PMF) you could
either set the PMF property "datanucleus.DetachAllOnCommit", or you could create your PMF and call the PMF method <strong>setDetachAllOnCommit(true)</strong>.
If instead you wanted to use this mode only for a particular PM, or only for a particular transaction for a particular PM, then you can call the PM method
<strong>setDetachAllOnCommit(true)</strong> before the commit of the transaction,
and it will apply for all transaction commits thereafter, until turned off (<strong>setDetachAllOnCommit(false)</strong>.
Here&#8217;s an example</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="comment">// Create a PMF</span>
...
<span class="comment">// Create an object</span>
MyObject my = <span class="keyword">new</span> MyObject();
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
<span class="keyword">try</span>
{
tx.begin();
<span class="comment">// We want our object to be detached when it's been persisted</span>
pm.setDetachAllOnCommit(<span class="predefined-constant">true</span>);
<span class="comment">// Persist the object that we created earlier</span>
pm.makePersistent(my);
tx.commit();
<span class="comment">// The object &quot;my&quot; is now in detached state and can be used further</span>
}
<span class="keyword">finally</span>
{
<span class="keyword">if</span> (tx.isActive)
{
tx.rollback();
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><br></p>
</div>
</div>
<div class="sect2">
<h3 id="copy_on_attach">Copy On Attach</h3>
<div class="paragraph">
<p>By default when you are attaching a detached object it will return an attached copy of the detached object.
JDO2.1 provides a new feature that allows this attachment to just migrate the existing detached object into attached state.</p>
</div>
<div class="paragraph">
<p>You enable this by setting the <em>PersistenceManagerFactory</em> (PMF) property <strong>datanucleus.CopyOnAttach</strong> to false.
Alternatively you can use the methods <em>PersistenceManagerFactory.setCopyOnAttach(boolean flag)</em> or <em>PersistenceManager.setCopyOnAttach(boolean flag)</em>.
If we return to the example at the start of this page, this now becomes</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="comment">// Reattach the updated object</span>
pm.setCopyOnAttach(<span class="predefined-constant">false</span>);
tx = pm.currentTransaction();
<span class="keyword">try</span>
{
tx.begin();
<span class="comment">// working product is currently in detached state</span>
pm.makePersistent(working_product);
<span class="comment">// working_product is now in persistent (attached) state</span>
tx.commit();
}
<span class="keyword">catch</span> (<span class="exception">Exception</span> e)
{
<span class="comment">// Handle the exception</span>
}
<span class="keyword">finally</span>
{
<span class="keyword">if</span> (tx.isActive())
{
tx.rollback();
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Please note that if you try to attach two detached objects representing
the same underlying persistent object within the same transaction (i.e a
persistent object with the same identity already exists in the level 1
cache), then a JDOUserException will be thrown.</p>
</div>
<div class="paragraph">
<p><br></p>
</div>
</div>
<div class="sect2">
<h3 id="serailization">Serialization of Detachable classes</h3>
<div class="paragraph">
<p>During enhancement of Detachable classes, a field called <em>jdoDetachedState</em> is added to the class definition.
This field allows reading and changing tracking of detached objects while they are not managed by a PersistenceManager.</p>
</div>
<div class="paragraph">
<p>When serialization occurs on a Detachable object, the <em>jdoDetachedState</em> field is written to the serialized object stream.
On deserialize, this field is written back to the new deserialized instance.
This process occurs transparently to the application.
However, if deserialization occurs with an un-enhanced version of the class, the detached state is lost.</p>
</div>
<div class="paragraph">
<p>Serialization and deserialization of Detachable classes and un-enhanced
versions of the same class is only possible if the field <em>serialVersionUID</em> is added.
It&#8217;s recommended during development of the class, to define the <em>serialVersionUID</em> and make the class to implement
the <em>java.io.Serializable</em> interface, as the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="type">class</span> <span class="class">MyClass</span> <span class="directive">implements</span> java.io.Serializable
{
<span class="directive">private</span> <span class="directive">static</span> <span class="directive">final</span> <span class="type">long</span> serialVersionUID = <span class="integer">2765740961462495537L</span>; <span class="comment">// any random value here</span>
<span class="comment">//.... other fields</span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><br></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<nav id="toc" data-spy="affix" data-toggle="toc"></nav>
</div>
</div>
</div>
<footer style="color:#fff; background-color:#222222; padding: 5px;">
<div class="container">
<div class="row" style="margin-top:25px">
<div class="col-sm" align="center">
<a href="https://www.facebook.com/JavaDataObjects" class="externalLink" title="Facebook">Facebook</a>
|
<a href="https://twitter.com/JavaDataObjects" class="externalLink" title="Twitter">Twitter</a>
|
<a href="http://wiki.apache.org/jdo" class="externalLink" title="Wiki">Wiki</a>
|
<a href="http://issues.apache.org/jira/secure/BrowseProject.jspa?id=10630" class="externalLink" title="Issue Tracker">Issue Tracker</a>
|
<a href="mail-lists.html" title="Mailing Lists">Mailing Lists</a>
|
<a href="api31/apidocs/index.html" title="Latest Javadocs">Latest Javadocs</a>
|
<a href="https://privacy.apache.org/policies/privacy-policy-public.html" title="Privacy Policy">Privacy Policy</a>
</div>
</div>
<p class="text-center" style="margin-top:16px">&copy; 2005-2022 Apache Software Foundation. All Rights Reserved.</p>
</div>
</footer>
</body>
</html>