-
Notifications
You must be signed in to change notification settings - Fork 130
/
ref_guide_pc.xml
2377 lines (2326 loc) · 97.3 KB
/
ref_guide_pc.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2006 The Apache Software Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<chapter id="ref_guide_pc">
<title>
Persistent Classes
</title>
<indexterm zone="ref_guide_pc">
<primary>
persistent classes
</primary>
</indexterm>
<para>
Persistent class basics are covered in <xref linkend="jpa_overview_pc"/>
of the JPA Overview. This chapter details the persistent class features OpenJPA
offers beyond the core JPA specification.
</para>
<section id="ref_guide_pc_pcclasses">
<title>
Persistent Class List
</title>
<indexterm zone="ref_guide_pc_pcclasses">
<primary>
persistent classes
</primary>
<secondary>
list
</secondary>
</indexterm>
<indexterm zone="ref_guide_pc_pcclasses">
<primary>
PCClasses
</primary>
</indexterm>
<para>
Unlike many ORM products, OpenJPA does not need to know about all of your
persistent classes at startup. OpenJPA discovers new persistent classes
automatically as they are loaded into the JVM; in fact you can introduce new
persistent classes into running applications under OpenJPA. However, there are
certain situations in which providing OpenJPA with a persistent class list is
helpful:
</para>
<itemizedlist>
<listitem>
<para>
OpenJPA must be able to match entity names in JPQL queries to persistent
classes. OpenJPA automatically knows the entity names of any persistent classes
already loaded into the JVM. To match entity names to classes that have not been
loaded, however, you must supply a persistent class list.
</para>
</listitem>
<listitem>
<para>
When OpenJPA manipulates classes in a persistent inheritance hierarchy, OpenJPA
must be aware of all the classes in the hierarchy. If some of the classes have
not been loaded into the JVM yet, OpenJPA may not know about them, and queries
may return incorrect results.
</para>
</listitem>
<listitem>
<para>
If you configure OpenJPA to create the needed database schema on startup (see
<xref linkend="ref_guide_mapping_synch"/>), OpenJPA must know all of your
persistent classes up-front.
</para>
</listitem>
</itemizedlist>
<para>
When any of these conditions are a factor in your JPA application, use the
<literal>class</literal>, <literal>mapping-file</literal>, and <literal>
jar-file</literal> elements of JPA's standard XML format to list your persistent
classes. See <xref linkend="jpa_overview_persistence_xml"/> for details.
</para>
<note>
<para>
Listing persistent classes (or their metadata or jar files) is an all-or-nothing
endeavor. If your persistent class list is non-empty, OpenJPA will assume that
any unlisted class is not persistent.
</para>
</note>
</section>
<section id="ref_guide_pc_enhance">
<title>
Enhancement
</title>
<indexterm zone="ref_guide_pc_enhance">
<primary>
enhancer
</primary>
</indexterm>
<indexterm>
<primary>
openjpac
</primary>
<see>
enhancer
</see>
</indexterm>
<para>
In order to provide optimal runtime performance, flexible lazy loading, and
efficient, immediate dirty tracking, OpenJPA uses an <emphasis> enhancer
</emphasis>. An enhancer is a tool that automatically adds code to your
persistent classes after you have written them. The enhancer post-processes the
bytecode generated by your Java compiler, adding the necessary fields and
methods to implement the required persistence features. This bytecode
modification perfectly preserves the line numbers in stack traces and is
compatible with Java debuggers. In fact, the only change to debugging
is that the persistent setter and getter methods of entity classes using
property access will be prefixed with <literal>pc</literal> in stack traces and
step-throughs. For example, if your entity has a <methodname>getId</methodname>
method for persistent property <literal>id</literal>, and that method throws an
exception, the stack trace will report the exception from method <methodname>
pcgetId</methodname>. The line numbers, however, will correctly correspond to
the <methodname>getId</methodname> method in your source file.
</para>
<mediaobject>
<imageobject>
<!-- PNG image data, 509 x 133 (see README) -->
<imagedata fileref="img/enhancement.png" width="339px"/>
</imageobject>
</mediaobject>
<para>
The diagram above illustrates the compilation of a persistent class.
</para>
<para>
You can add the OpenJPA enhancer to your build process, or use Java 1.5's new
instrumentation features to transparently enhance persistent classes when they
are loaded into the JVM. The following sections describe each option.
</para>
<section id="ref_guide_pc_enhance_build">
<title>
Enhancing at Build Time
</title>
<indexterm zone="ref_guide_pc_enhance_build">
<primary>
enhancer
</primary>
<secondary>
build time
</secondary>
</indexterm>
<para>
The enhancer can be invoked at build time
via its Java class, <classname>
org.apache.openjpa.enhance.PCEnhancer</classname>.
</para>
<note>
<para>
You can also enhance via Ant; see
<xref linkend="ref_guide_integration_enhance"/>.
</para>
</note>
<example id="ref_guide_pc_enhance_enhancer">
<title>
Using the OpenJPA Enhancer
</title>
<programlisting>
java org.apache.openjpa.enhance.PCEnhancer Magazine.java
</programlisting>
</example>
<para>
The enhancer accepts the standard set of command-line arguments defined by the
configuration framework (see <xref linkend="ref_guide_conf_devtools"/> ),
along with the following flags:
</para>
<itemizedlist>
<listitem>
<para>
<literal>-directory/-d <output directory></literal>: Path to the output
directory. If the directory does not match the enhanced class' package, the
package structure will be created beneath the directory. By default, the
enhancer overwrites the original <filename>.class</filename> file.
</para>
</listitem>
<listitem>
<para>
<literal>-enforcePropertyRestrictions/-epr <true/t | false/f></literal>:
Whether to throw an exception when it appears that a property access entity is
not obeying the restrictions placed on property access. Defaults to false.
</para>
</listitem>
<listitem>
<para>
<literal>-addDefaultConstructor/-adc <true/t | false/f></literal>: The
spec requires that all persistent classes define a no-arg constructor. This flag
tells the enhancer whether to add a protected no-arg constructor to any
persistent classes that don't already have one. Defaults to <literal>
true</literal>.
</para>
</listitem>
<listitem>
<para>
<literal>-tmpClassLoader/-tcl <true/t | false/f></literal>: Whether to
load persistent classes with a temporary class loader. This allows other code to
then load the enhanced version of the class within the same JVM. Defaults to
<literal>true</literal>. Try setting this flag to <literal>false</literal> as a
debugging step if you run into class loading problems when running the enhancer.
</para>
</listitem>
</itemizedlist>
<para>
Each additional argument to the enhancer must be one of the following:
</para>
<itemizedlist>
<listitem>
<para>
The full name of a class.
</para>
</listitem>
<listitem>
<para>
The .java file for a class.
</para>
</listitem>
<listitem>
<para>
The <filename>.class</filename> file of a class.
</para>
</listitem>
</itemizedlist>
<para>
If you do not supply any arguments to the enhancer, it will run on the classes
in your persistent class list (see <xref linkend="ref_guide_pc_pcclasses"/>).
</para>
<para>
You can run the enhancer over classes that have already been enhanced, in which
case it will not further modify the class. You can also run it over classes that
are not persistence-capable, in which case it will treat the class as
persistence-aware. Persistence-aware classes can directly manipulate the
persistent fields of persistence-capable classes.
</para>
<para>
Note that the enhancement process for subclasses introduces dependencies on the
persistent parent class being enhanced. This is normally not problematic;
however, when running the enhancer multiple times over a subclass whose parent
class is not yet enhanced, class loading errors can occur. In the event of a
class load error, simply re-compile and re-enhance the offending classes.
</para>
</section>
<section id="ref_guide_pc_enhance_runtime_container">
<title>
Enhancing JPA Entities on Deployment
</title>
<indexterm zone="ref_guide_pc_enhance_runtime_container">
<primary>
enhancer
</primary>
<secondary>
runtime
</secondary>
<tertiary>
in an EJB container
</tertiary>
</indexterm>
<para>
The JEE 5 specification includes hooks to automatically enhance JPA entities
when they are deployed into a container. Thus, if you are using a JEE
5-compliant application server, OpenJPA will enhance your entities automatically
at runtime. Note that if you prefer build-time enhancement, OpenJPA's runtime
enhancer will correctly recognize and skip pre-enhanced classes.
</para>
<para>
If your application server does not support the JEE 5 enhancement hooks,
consider using the build-time enhancement described above, or the more general
runtime enhancement described in the next section.
</para>
</section>
<section id="ref_guide_pc_enhance_runtime">
<title>
Enhancing at Runtime
</title>
<indexterm zone="ref_guide_pc_enhance_runtime">
<primary>
enhancer
</primary>
<secondary>
runtime
</secondary>
<tertiary>
outside a container
</tertiary>
</indexterm>
<para>
OpenJPA includes a <emphasis>Java agent</emphasis> for automatically enhancing
persistent classes as they are loaded into the JVM. Java agents are classes that
are invoked prior to your application's <methodname>main</methodname> method.
OpenJPA's agent uses JVM hooks to intercept all class loading to enhance classes
that have persistence metadata before the JVM loads them.
</para>
<para>
Searching for metadata for every class loaded by the JVM can slow application
initialization. One way to speed things up is to take advantage of the optional
persistent class list described in <xref linkend="ref_guide_pc_pcclasses"/>. If
you declare a persistent class list, OpenJPA will only search for
metadata for classes in that list.
</para>
<para>
To employ the OpenJPA agent, invoke <literal>java</literal> with the <literal>
-javaagent</literal> set to the path to your OpenJPA jar file.
</para>
<example id="ref_guide_pc_enhance_runtime_ex">
<title>
Using the OpenJPA Agent for Runtime Enhancement
</title>
<programlisting>
java -javaagent:/home/dev/openjpa/lib/openjpa.jar com.xyz.Main
</programlisting>
</example>
<para>
You can pass settings to the agent using OpenJPA's plugin syntax (see
<xref linkend="ref_guide_conf_plugins"/>). The agent accepts the long
form of any of the standard configuration options
(<xref linkend="ref_guide_conf_devtools"/> ). It also accepts the following
options, the first three of which correspond exactly to to the same-named
options of the enhancer tool described in
<xref linkend="ref_guide_pc_enhance_build"/>:
</para>
<itemizedlist>
<listitem>
<para>
<literal>addDefaultConstructor</literal>
</para>
</listitem>
<listitem>
<para>
<literal>enforcePropertyRestrictions</literal>
</para>
</listitem>
<listitem>
<para>
<literal>scanDevPath</literal>: Boolean indicating whether to scan the
classpath for persistent types if none have been configured. If you do not
specify a persistent types list and do not set this option to true, OpenJPA will
check whether each class loaded into the JVM is persistent, and enhance it
accordingly. This may slow down class load times significantly.
</para>
</listitem>
</itemizedlist>
<example id="ref_guide_pc_enhance_runtime_opt_ex">
<title>
Passing Options to the OpenJPA Agent
</title>
<programlisting>
java -javaagent:/home/dev/openjpa/lib/openjpa.jar=addDefaultConstructor=false com.xyz.Main
</programlisting>
</example>
</section>
<section id="ref_guide_pc_enhance_sercompat">
<title>
Serializing Enhanced Types
</title>
<indexterm zone="ref_guide_pc_enhance_sercompat">
<primary>
enhancer
</primary>
<secondary>
serialization
</secondary>
<tertiary>
of enhanced types
</tertiary>
</indexterm>
<indexterm zone="ref_guide_pc_enhance_sercompat">
<primary>
serialization
</primary>
<secondary>
of enhanced types
</secondary>
</indexterm>
<para>
By default, OpenJPA maintains serialization compatibility between the enhanced
and unenhanced versions of a class. This allows you to serialize instances
between a server using OpenJPA and a client that does not have access to
enhanced classes or OpenJPA libraries. In some cases, however, you can make the
persist and attach processes more robust and efficient by allowing breaks in
serialization compatibility. See <xref linkend="ref_guide_detach_graph"/>
for details.
</para>
</section>
</section>
<section id="ref_guide_pc_oid">
<title>
Object Identity
</title>
<indexterm zone="ref_guide_pc_oid">
<primary>
identity
</primary>
</indexterm>
<para>
OpenJPA makes several enhancements to JPA's standard entity identity.
</para>
<section id="ref_guide_pc_oid_datastore">
<title>
Datastore Identity
</title>
<indexterm zone="ref_guide_pc_oid_datastore">
<primary>
identity
</primary>
<secondary>
datastore
</secondary>
</indexterm>
<para>
The JPA specification requires you to declare one or more identity fields in
your persistent classes. OpenJPA fully supports this form of object identity,
called <emphasis>application</emphasis> identity. OpenJPA, however, also
supports <emphasis>datastore</emphasis> identity. In datastore identity, you do
not declare any primary key fields. OpenJPA manages the identity of your
persistent objects for you through a surrogate key in the database.
</para>
<para>
You can control how your JPA datastore identity value is generated through
OpenJPA's
<ulink url="../javadoc/org/apache/openjpa/persistence/DataStoreId.html">
<classname>org.apache.openjpa.persistence.DataStoreId</classname></ulink> class
annotation. This annotation has <literal>strategy</literal> and <literal>
generator</literal> properties that mirror the same-named properties on the
standard <classname>javax.persistence.GeneratedValue</classname> annotation
described in <xref linkend="jpa_overview_meta_id"/> of the JPA Overview.
</para>
<para>
To retrieve the identity value of a datastore identity entity, use the
<methodname>OpenJPAEntityManager.getObjectId(Object entity)</methodname>
method. See <xref linkend="ref_guide_runtime_em"/> for more information on
the <classname>OpenJPAEntityManager</classname>.
</para>
<example id="ref_guide_pc_oid_datastoreentityex">
<title>
JPA Datastore Identity Metadata
</title>
<programlisting>
import org.apache.openjpa.persistence.*;
@Entity
@DataStoreId
public class LineItem {
... no @Id fields declared ...
}
</programlisting>
</example>
<para>
Internally, OpenJPA uses the public
<ulink url="../javadoc/org/apache/openjpa/util/Id.html"><classname>
org.apache.openjpa.util.Id</classname></ulink> class for datastore identity
objects. When writing OpenJPA plugins, you can manipulate datastore identity
objects by casting them to this class. You can also create your own <classname>
Id</classname> instances and pass them to any internal OpenJPA method that
expects an identity object.
</para>
<para>
In JPA, you will never see <classname>Id</classname> instances directly.
Instead, calling <classname>OpenJPAEntityManager.getObjectId</classname> on a
datastore identity object will return the <classname>Long</classname> surrogate
primary key value for that object. You can then use this value in calls to
<classname>EntityManager.find</classname> for subsequent lookups of the same
record.
</para>
</section>
<section id="ref_guide_pc_oid_entitypk">
<title>
Entities as Identity Fields
</title>
<indexterm zone="ref_guide_pc_oid_entitypk">
<primary>
identity
</primary>
<secondary>
application
</secondary>
<tertiary>
entity id fields
</tertiary>
</indexterm>
<para>
The JPA specification limits identity fields to simple types. OpenJPA, however,
also allows <literal>ManyToOne</literal> and <literal>OneToOne</literal>
relations to be identity fields. To identify a relation field as an identity
field, simply annotate it with both the <literal>@ManyToOne</literal> or
<literal>@OneToOne</literal> relation annotation and the <literal>@Id</literal>
identity annotation.
</para>
<para>
When finding an entity identified by a relation, pass the id of the
<emphasis>relation</emphasis> to the <methodname>EntityManager.find</methodname>
method:
</para>
<example id="ref_guide_pc_oid_entitypk_simplefind">
<title>
Finding an Entity with an Entity Identity Field
</title>
<programlisting>
public Delivery createDelivery(EntityManager em, Order order) {
Delivery delivery = new Delivery();
delivery.setId(o);
delivery.setDelivered(new Date());
return delivery;
}
public Delivery findDelivery(EntityManager em, Order order) {
// use the identity of the related instance
return em.find(Delivery.class, order.getId());
}
</programlisting>
</example>
<para>
When your entity has multiple identity fields, at least one of which is a
relation to another entity, you must use an identity class (see
<xref linkend="jpa_overview_pc_identitycls"/> in the JPA Overview). You cannot
use an embedded identity object. Identity class fields corresponding to
entity identity fields should be of the same type as the related entity's
identity.
</para>
<example id="ref_guide_pc_oid_entitypk_idcls">
<title>
Id Class for Entity Identity Fields
</title>
<programlisting>
@Entity
public class Order {
@Id
private long id;
...
}
@Entity
@IdClass(LineItemId.class)
public class LineItem {
@Id
private int index;
@Id
@ManyToOne
private Order order;
...
}
public class LineItemId {
public int index;
public long order; // same type as order's identity
...
}
</programlisting>
</example>
<para>
In the example above, if <classname>Order</classname> had used an identity
class <classname>OrderId</classname> in place of a simple <classname>long
</classname> value, then the <literal>LineItemId.order</literal> field would
have been of type <classname>OrderId</classname>.
</para>
</section>
<section id="ref_guide_pc_oid_application">
<title>
Application Identity Tool
</title>
<indexterm zone="ref_guide_pc_oid_application">
<primary>
identity
</primary>
<secondary>
application
</secondary>
<tertiary>
application identity tool
</tertiary>
</indexterm>
<indexterm zone="ref_guide_pc_oid_application">
<primary>
application identity tool
</primary>
</indexterm>
<para>
If you choose to use application identity, you may want to take advantage of
OpenJPA's application identity tool. The application
identity tool generates Java code implementing the identity class for any
persistent type using application identity. The code satisfies all the
requirements the specification places on identity classes. You can use it as-is,
or simply use it as a starting point, editing it to meet your needs.
</para>
<para>
Before you can run the application identity tool on a persistent class, the
class must be compiled and must have complete metadata. All primary key fields
must be marked as such in the metadata.
</para>
<para>
In JPA metadata, do not attempt to specify the <literal>@IdClass</literal>
annotation unless you are using the application identity tool to overwrite an
existing identity class. Attempting to set the value of the <literal>@IdClass
</literal> to a non-existent class will prevent your persistent class from
compiling. Instead, use the <literal>-name</literal> or <literal>-suffix
</literal> options described below to tell OpenJPA what name to give your
generated identity class. Once the application identity tool has generated the
class code, you can set the <literal>@IdClass</literal> annotation.
</para>
<para>
The application identity tool can be invoked via its Java class,
<ulink url="../javadoc/org/apache/openjpa/enhance/ApplicationIdTool">
<classname>org.apache.openjpa.enhance.ApplicationIdTool</classname></ulink>.
</para>
<note>
<para>
<xref linkend="ref_guide_integration_appidtool"/> describes the
application identity tool's Ant task.
</para>
</note>
<example id="ref_guide_pc_appid_appidtool">
<title>
Using the Application Identity Tool
</title>
<programlisting>
java org.apache.openjpa.enhance.ApplicationIdTool -s Id Magazine.java
</programlisting>
</example>
<para>
The application identity tool accepts the standard set of command-line arguments
defined by the configuration framework (see
<xref linkend="ref_guide_conf_devtools"/>), including code formatting
flags described in <xref linkend="ref_guide_conf_devtools_format"/>. It
also accepts the following arguments:
</para>
<itemizedlist>
<listitem>
<para>
<literal>-directory/-d <output directory></literal>: Path to the output
directory. If the directory does not match the generated oid class' package, the
package structure will be created beneath the directory. If not specified, the
tool will first try to find the directory of the <filename>.java</filename> file
for the persistence-capable class, and failing that will use the current
directory.
</para>
</listitem>
<listitem>
<para>
<literal>-ignoreErrors/-i <true/t | false/f></literal>: If <literal>false
</literal>, an exception will be thrown if the tool is run on any class that
does not use application identity, or is not the base class in the inheritance
hierarchy (recall that subclasses never define the application identity class;
they inherit it from their persistent superclass).
</para>
</listitem>
<listitem>
<para>
<literal>-token/-t <token></literal>: The token to use to separate
stringified primary key values in the string form of the object id. This option
is only used if you have multiple primary key fields. It defaults to "::".
</para>
</listitem>
<listitem>
<para>
<literal>-name/-n <id class name></literal>: The name of the identity
class to generate. If this option is specified, you must run the tool on exactly
one class. If the class metadata already names an object id class, this option
is ignored. If the name is not fully qualified, the persistent class' package is
prepended to form the qualified name.
</para>
</listitem>
<listitem>
<para>
<literal>-suffix/-s <id class suffix></literal>: A string to suffix each
persistent class name with to form the identity class name. This option is
overridden by <literal>-name</literal> or by any object id class specified in
metadata.
</para>
</listitem>
</itemizedlist>
<para>
Each additional argument to the tool must be one of the following:
</para>
<itemizedlist>
<listitem>
<para>
The full name of a persistent class.
</para>
</listitem>
<listitem>
<para>
The .java file for a persistent class.
</para>
</listitem>
<listitem>
<para>
The <filename>.class</filename> file of a persistent class.
</para>
</listitem>
</itemizedlist>
<para>
If you do not supply any arguments to the tool, it will act on the classes in
your persistent classes list (see <xref linkend="ref_guide_pc_pcclasses"/>).
</para>
</section>
<section id="ref_guide_pc_oid_pkgen_autoinc">
<title>
Autoassign / Identity Strategy Caveats
</title>
<indexterm zone="ref_guide_pc_oid_pkgen_autoinc">
<primary>
datastore identity
</primary>
<secondary>
autoassign strategy
</secondary>
</indexterm>
<indexterm zone="ref_guide_pc_oid_pkgen_autoinc">
<primary>
datastore identity
</primary>
<secondary>
autoassign strategy
</secondary>
</indexterm>
<indexterm zone="ref_guide_pc_oid_pkgen_autoinc">
<primary>
persistent fields
</primary>
<secondary>
autoassign strategy
</secondary>
</indexterm>
<para>
<xref linkend="jpa_overview_meta_gen"/> explains how to use JPA's
<literal>IDENTITY</literal> generation type to automatically assign field
values. However, here are some additional caveats you should be aware of when
using <literal>IDENTITY</literal> generation:
</para>
<orderedlist>
<listitem>
<para>
Your database must support auto-increment / identity columns, or some equivalent
(see <xref linkend="ref_guide_dbsetup_dbsupport_oracle"/> for how to
configure a combination of triggers and sequences to fake auto-increment support
in Oracle).
</para>
</listitem>
<listitem>
<para>
Auto-increment / identity columns must be an integer or long integer type.
</para>
</listitem>
<listitem>
<para>
Databases support auto-increment / identity columns to varying degrees. Some do
not support them at all. Others only allow a single such column per table, and
require that it be the primary key column. More lenient databases may allow
non-primary key auto-increment columns, and may allow more than one per table.
See your database documentation for details.
</para>
</listitem>
</orderedlist>
</section>
</section>
<section id="ref_guide_inverses">
<title>
Managed Inverses
</title>
<indexterm zone="ref_guide_inverses">
<primary>
bidirectional relations
</primary>
<secondary>
automatic management
</secondary>
</indexterm>
<para>
Bidirectional relations are an essential part of data modeling.
<xref linkend="jpa_overview_mapping"/> in the JPA Overview explains how to
use the <literal>mappedBy</literal> annotation attribute to form bidirectional
relations that also share datastore storage in JPA.
</para>
<para>
OpenJPA also allows you to define purely logical bidirectional relations. The
<ulink url="../javadoc/org/apache/openjpa/persistence/InverseLogical.html">
<classname>org.apache.openjpa.persistence.InverseLogical</classname></ulink>
annotation names a logical inverse in JPA metadata.
</para>
<example id="ref_guide_inverses_logicalex">
<title>
Specifying Logical Inverses
</title>
<para>
<literal>Magazine.coverPhoto</literal> and <literal>Photograph.mag</literal> are
each mapped to different foreign keys in their respective tables, but form a
logical bidirectional relation. Only one of the fields needs to declare the
other as its logical inverse, though it is not an error to set the logical
inverse of both fields.
</para>
<programlisting>
import org.apache.openjpa.persistence.*;
@Entity
public class Magazine {
@OneToOne
private Photograph coverPhoto;
...
}
@Entity
public class Photograph {
@OneToOne
@InverseLogical("coverPhoto")
private Magazine mag;
...
}
</programlisting>
</example>
<para>
Java does not provide any native facilities to ensure that both sides of a
bidirectional relation remain consistent. Whenever you set one side of the
relation, you must manually set the other side as well.
</para>
<para>
By default, OpenJPA behaves the same way. OpenJPA does not automatically
propagate changes from one field in bidirectional relation to the other field.
This is in keeping with the philosophy of transparency, and also provides higher
performance, as OpenJPA does not need to analyze your object graph to correct
inconsistent relations.
</para>
<para>
<indexterm>
<primary>
InverseManager
</primary>
</indexterm>
If convenience is more important to you than strict transparency, however, you
can enable inverse relation management in OpenJPA. Set the
<link linkend="openjpa.InverseManager"><classname>openjpa.InverseManager
</classname></link> plugin property to <literal>true</literal> for standard
management. Under this setting, OpenJPA detects changes to either side of a
bidirectional relation (logical or physical), and automatically sets the other
side appropriately on flush.
</para>
<example id="ref_guide_inversesex">
<title>
Enabling Managed Inverses
</title>
<programlisting>
<property name="openjpa.InverseManager" value="true"/>
</programlisting>
</example>
<para>
The inverse manager has options to log a warning or throw an exception when it
detects an inconsistent bidirectional relation, rather than correcting it. To
use these modes, set the manager's <literal>Action</literal> property to
<literal>warn</literal> or <literal>exception</literal>, respectively.
</para>
<para>
By default, OpenJPA excludes <link linkend="ref_guide_pc_scos_proxy_lrs"> large
result set fields</link> from management. You can force large result set fields
to be included by setting the <literal>ManageLRS</literal> plugin property to
<literal>true</literal>.
</para>
<example id="ref_guide_inverses_logex">
<title>
Log Inconsistencies
</title>
<programlisting>
<property name="openjpa.InverseManager" value="true(Action=warn)"/>
</programlisting>
</example>
</section>
<section id="ref_guide_pc_scos">
<title>
Persistent Fields
</title>
<indexterm zone="ref_guide_pc_scos">
<primary>
persistent fields
</primary>
</indexterm>
<para>
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.
</para>
<section id="ref_guide_pc_scos_restore">
<title>
Restoring State
</title>
<indexterm zone="ref_guide_pc_scos">
<primary>
persistent fields
</primary>
<secondary>
field rollback
</secondary>
</indexterm>
<indexterm zone="ref_guide_pc_scos_restore">
<primary>
RestoreState
</primary>
</indexterm>
<para>
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
<link linkend="openjpa.RestoreState"><literal>openjpa.RestoreState</literal>
</link> configuration property. <literal>none</literal> does not roll back state
(the object becomes hollow, and will re-load its state the next time it is
accessed), <literal>immutable</literal> restores immutable values (primitives,
primitive wrappers, strings) and clears mutable values so that they are reloaded
on next access, and <literal>all</literal> restores all managed values to their
pre-transaction state.
</para>
</section>
<section id="ref_guide_pc_scos_order">
<title>
Typing and Ordering
</title>
<indexterm zone="ref_guide_pc_scos_order">
<primary>
persistent fields
</primary>
<secondary>
comparators
</secondary>
</indexterm>
<para>
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.
</para>
<example id="ref_guide_pc_scos_order_initialvals">
<title>
Using Initial Field Values
</title>
<para>
Though the annotations are left out for simplicity, assume <literal>
employeesBySal</literal> and <literal>departments</literal> are persistent
fields in the class below.
</para>
<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...
}
</programlisting>
</example>
</section>
<section id="ref_guide_pc_calendar_timezone">
<title>
Calendar Fields and TimeZones
</title>
<indexterm zone="ref_guide_pc_calendar_timezone">
<primary>
persistent fields
</primary>
<secondary>
calendar
</secondary>
</indexterm>
<para>
OpenJPA's support for the <classname>java.util.Calendar</classname> type will
store only the <classname>Date</classname> part of the field, not the
<classname>TimeZone</classname> associated with the field. When loading the date
into the <classname>Calendar</classname> field, OpenJPA will use the <classname>
TimeZone</classname> that was used to initialize the field.
</para>
<note>
<para>