Source Code Cross Referenced for SecondaryIndex.java in  » JMX » je » com » sleepycat » persist » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » JMX » je » com.sleepycat.persist 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*-
002:         * See the file LICENSE for redistribution information.
003:         *
004:         * Copyright (c) 2002,2008 Oracle.  All rights reserved.
005:         *
006:         * $Id: SecondaryIndex.java,v 1.14.2.3 2008/01/07 15:14:18 cwl Exp $
007:         */
008:
009:        package com.sleepycat.persist;
010:
011:        import java.util.Map;
012:        import java.util.SortedMap;
013:
014:        import com.sleepycat.bind.EntityBinding;
015:        import com.sleepycat.bind.EntryBinding;
016:        import com.sleepycat.collections.StoredSortedMap;
017:        import com.sleepycat.je.Database;
018:        import com.sleepycat.je.DatabaseConfig;
019:        import com.sleepycat.je.DatabaseEntry;
020:        import com.sleepycat.je.DatabaseException;
021:        import com.sleepycat.je.LockMode;
022:        import com.sleepycat.je.OperationStatus;
023:        import com.sleepycat.je.SecondaryDatabase;
024:        import com.sleepycat.je.Transaction;
025:        import com.sleepycat.persist.model.DeleteAction;
026:        import com.sleepycat.persist.model.Relationship;
027:        import com.sleepycat.persist.model.SecondaryKey;
028:
029:        /**
030:         * The secondary index for an entity class and a secondary key.
031:         *
032:         * <p>{@code SecondaryIndex} objects are thread-safe.  Multiple threads may
033:         * safely call the methods of a shared {@code SecondaryIndex} object.</p>
034:         *
035:         * <p>{@code SecondaryIndex} implements {@link EntityIndex} to map the
036:         * secondary key type (SK) to the entity type (E).  In other words, entities
037:         * are accessed by secondary key values.</p>
038:         *
039:         * <p>The {@link SecondaryKey} annotation may be used to define a secondary key
040:         * as shown in the following example.</p>
041:         *
042:         * <pre class="code">
043:         * {@literal @Entity}
044:         * class Employee {
045:         *
046:         *     {@literal @PrimaryKey}
047:         *     long id;
048:         *
049:         *     {@literal @SecondaryKey(relate=MANY_TO_ONE)}
050:         *     String department;
051:         *
052:         *     String name;
053:         *
054:         *     private Employee() {}
055:         * }</pre>
056:         *
057:         * <p>Before obtaining a {@code SecondaryIndex}, the {@link PrimaryIndex} must
058:         * be obtained for the entity class.  To obtain the {@code SecondaryIndex} call
059:         * {@link EntityStore#getSecondaryIndex EntityStore.getSecondaryIndex}, passing
060:         * the primary index, the secondary key class and the secondary key name.  For
061:         * example:</p>
062:         *
063:         * <pre class="code">
064:         * EntityStore store = new EntityStore(...);
065:         *
066:         * {@code PrimaryIndex<Long,Employee>} primaryIndex =
067:         *     store.getPrimaryIndex(Long.class, Employee.class);
068:         *
069:         * {@code SecondaryIndex<String,Long,Employee>} secondaryIndex =
070:         *     store.getSecondaryIndex(primaryIndex, String.class, "department");</pre>
071:         *
072:         * <p>Since {@code SecondaryIndex} implements the {@link EntityIndex}
073:         * interface, it shares the common index methods for retrieving and deleting
074:         * entities, opening cursors and using transactions.  See {@link EntityIndex}
075:         * for more information on these topics.</p>
076:         *
077:         * <p>{@code SecondaryIndex} does <em>not</em> provide methods for inserting
078:         * and updating entities.  That must be done using the {@link
079:         * PrimaryIndex}.</p>
080:         *
081:         * <p>Note that a {@code SecondaryIndex} has three type parameters {@code
082:         * <SK,PK,E>} or in the example {@code <String,Long,Employee>} while a {@link
083:         * PrimaryIndex} has only two type parameters {@code <PK,E>} or {@code
084:         * <Long,Employee>}.  This is because a {@code SecondaryIndex} has an extra
085:         * level of mapping:  It maps from secondary key to primary key, and then from
086:         * primary key to entity.  For example, consider this entity:</p>
087:         *
088:         * <p><table class="code" border="1">
089:         *   <tr><th>ID</th><th>Department</th><th>Name</th></tr>
090:         *   <tr><td>1</td><td>Engineering</td><td>Jane Smith</td></tr>
091:         * </table></p>
092:         *
093:         * <p>The {@link PrimaryIndex} maps from id directly to the entity, or from
094:         * primary key 1 to the "Jane Smith" entity in the example.  The {@code
095:         * SecondaryIndex} maps from department to id, or from secondary key
096:         * "Engineering" to primary key 1 in the example, and then uses the {@code
097:         * PrimaryIndex} to map from the primary key to the entity.</p>
098:         *
099:         * <p>Because of this extra type parameter and extra level of mapping, a {@code
100:         * SecondaryIndex} can provide more than one mapping, or view, of the entities
101:         * in the primary index.  The main mapping of a {@code SecondaryIndex} is to
102:         * map from secondary key (SK) to entity (E), or in the example, from the
103:         * String department key to the Employee entity.  The {@code SecondaryIndex}
104:         * itself, by implementing {@code EntityIndex<SK,E>}, provides this
105:         * mapping.</p>
106:         *
107:         * <p>The second mapping provided by {@code SecondaryIndex} is from secondary
108:         * key (SK) to primary key (PK), or in the example, from the String department
109:         * key to the Long id key.  The {@link #keysIndex} method provides this
110:         * mapping.  When accessing the keys index, the primary key is returned rather
111:         * than the entity.  When only the primary key is needed and not the entire
112:         * entity, using the keys index is less expensive than using the secondary
113:         * index because the primary index does not have to be accessed.</p>
114:         *
115:         * <p>The third mapping provided by {@code SecondaryIndex} is from primary key
116:         * (PK) to entity (E), for the subset of entities having a given secondary key
117:         * (SK).  This mapping is provided by the {@link #subIndex} method.  A
118:         * sub-index is convenient when you are interested in working with the subset
119:         * of entities having a particular secondary key value, for example, all
120:         * employees in a given department.</p>
121:         *
122:         * <p>All three mappings, along with the mapping provided by the {@link
123:         * PrimaryIndex}, are shown using example data in the {@link EntityIndex}
124:         * interface documentation.  See {@link EntityIndex} for more information.</p>
125:         *
126:         * <p>Note that when using an index, keys and values are stored and retrieved
127:         * by value not by reference.  In other words, if an entity object is stored
128:         * and then retrieved, or retrieved twice, each object will be a separate
129:         * instance.  For example, in the code below the assertion will always
130:         * fail.</p>
131:         * <pre class="code">
132:         * MyKey key = ...;
133:         * MyEntity entity1 = index.get(key);
134:         * MyEntity entity2 = index.get(key);
135:         * assert entity1 == entity2; // always fails!
136:         * </pre>
137:         *
138:         * <h3>One-to-One Relationships</h3>
139:         *
140:         * <p>A {@link Relationship#ONE_TO_ONE ONE_TO_ONE} relationship, although less
141:         * common than other types of relationships, is the simplest type of
142:         * relationship.  A single entity is related to a single secondary key value.
143:         * For example:</p>
144:         *
145:         * <pre class="code">
146:         * {@literal @Entity}
147:         * class Employee {
148:         *
149:         *     {@literal @PrimaryKey}
150:         *     long id;
151:         *
152:         *     {@literal @SecondaryKey(relate=ONE_TO_ONE)}
153:         *     String ssn;
154:         *
155:         *     String name;
156:         *
157:         *     private Employee() {}
158:         * }
159:         *
160:         * {@code SecondaryIndex<String,Long,Employee>} employeeBySsn =
161:         *     store.getSecondaryIndex(primaryIndex, String.class, "ssn");</pre>
162:         *
163:         * <p>With a {@link Relationship#ONE_TO_ONE ONE_TO_ONE} relationship, the
164:         * secondary key must be unique; in other words, no two entities may have the
165:         * same secondary key value.  If an attempt is made to store an entity having
166:         * the same secondary key value as another existing entity, a {@link
167:         * DatabaseException} will be thrown.</p>
168:         *
169:         * <p>Because the secondary key is unique, it is useful to lookup entities by
170:         * secondary key using {@link EntityIndex#get}.  For example:</p>
171:         *
172:         * <pre class="code">
173:         * Employee employee = employeeBySsn.get(mySsn);</pre>
174:         *
175:         * <h3>Many-to-One Relationships</h3>
176:         *
177:         * <p>A {@link Relationship#MANY_TO_ONE MANY_TO_ONE} relationship is the most
178:         * common type of relationship.  One or more entities is related to a single
179:         * secondary key value.  For example:</p>
180:         *
181:         * <pre class="code">
182:         * {@literal @Entity}
183:         * class Employee {
184:         *
185:         *     {@literal @PrimaryKey}
186:         *     long id;
187:         *
188:         *     {@literal @SecondaryKey(relate=MANY_TO_ONE)}
189:         *     String department;
190:         *
191:         *     String name;
192:         *
193:         *     private Employee() {}
194:         * }
195:         *
196:         * {@code SecondaryIndex<String,Long,Employee>} employeeByDepartment =
197:         *     store.getSecondaryIndex(primaryIndex, String.class, "department");</pre>
198:         *
199:         * <p>With a {@link Relationship#MANY_TO_ONE MANY_TO_ONE} relationship, the
200:         * secondary key is not required to be unique; in other words, more than one
201:         * entity may have the same secondary key value.  In this example, more than
202:         * one employee may belong to the same department.</p>
203:         *
204:         * <p>The most convenient way to access the employees in a given department is
205:         * by using a sub-index.  For example:</p>
206:         *
207:         * <pre class="code">
208:         * {@code EntityIndex<Long,Entity>} subIndex = employeeByDepartment.subIndex(myDept);
209:         * {@code EntityCursor<Employee>} cursor = subIndex.entities();
210:         * try {
211:         *     for (Employee entity : cursor) {
212:         *         // Do something with the entity...
213:         *     }
214:         * } finally {
215:         *     cursor.close();
216:         * }</pre>
217:         *
218:         * <h3>One-to-Many Relationships</h3>
219:         *
220:         * <p>In a {@link Relationship#ONE_TO_MANY ONE_TO_MANY} relationship, a single
221:         * entity is related to one or more secondary key values.  For example:</p>
222:         *
223:         * <pre class="code">
224:         * {@literal @Entity}
225:         * class Employee {
226:         *
227:         *     {@literal @PrimaryKey}
228:         *     long id;
229:         *
230:         *     {@literal @SecondaryKey(relate=ONE_TO_MANY)}
231:         *     {@literal Set<String> emailAddresses = new HashSet<String>;}
232:         *
233:         *     String name;
234:         *
235:         *     private Employee() {}
236:         * }
237:         *
238:         * {@code SecondaryIndex<String,Long,Employee>} employeeByEmail =
239:         *     store.getSecondaryIndex(primaryIndex, String.class, "emailAddresses");</pre>
240:         *
241:         * <p>With a {@link Relationship#ONE_TO_MANY ONE_TO_MANY} relationship, the
242:         * secondary key must be unique; in other words, no two entities may have the
243:         * same secondary key value.  In this example, no two employees may have the
244:         * same email address.  If an attempt is made to store an entity having the
245:         * same secondary key value as another existing entity, a {@link
246:         * DatabaseException} will be thrown.</p>
247:         *
248:         * <p>Because the secondary key is unique, it is useful to lookup entities by
249:         * secondary key using {@link EntityIndex#get}.  For example:</p>
250:         *
251:         * <pre class="code">
252:         * Employee employee = employeeByEmail.get(myEmailAddress);</pre>
253:         *
254:         * <p>The secondary key field for a {@link Relationship#ONE_TO_MANY
255:         * ONE_TO_MANY} relationship must be an array or collection type.  To access
256:         * the email addresses of an employee, simply access the collection field
257:         * directly.  For example:</p>
258:         *
259:         * <pre class="code">
260:         * Employee employee = primaryIndex.get(1); // Get the entity by primary key
261:         * employee.emailAddresses.add(myNewEmail); // Add an email address
262:         * primaryIndex.putNoReturn(1, employee);   // Update the entity</pre>
263:         *
264:         * <h3>Many-to-Many Relationships</h3>
265:         *
266:         * <p>In a {@link Relationship#MANY_TO_MANY MANY_TO_MANY} relationship, one
267:         * or more entities is related to one or more secondary key values.  For
268:         * example:</p>
269:         *
270:         * <pre class="code">
271:         * {@literal @Entity}
272:         * class Employee {
273:         *
274:         *     {@literal @PrimaryKey}
275:         *     long id;
276:         *
277:         *     {@literal @SecondaryKey(relate=MANY_TO_MANY)}
278:         *     {@literal Set<String> organizations = new HashSet<String>;}
279:         *
280:         *     String name;
281:         *
282:         *     private Employee() {}
283:         * }
284:         *
285:         * {@code SecondaryIndex<String,Long,Employee>} employeeByOrganization =
286:         *     store.getSecondaryIndex(primaryIndex, String.class, "organizations");</pre>
287:         *
288:         * <p>With a {@link Relationship#MANY_TO_MANY MANY_TO_MANY} relationship, the
289:         * secondary key is not required to be unique; in other words, more than one
290:         * entity may have the same secondary key value.  In this example, more than
291:         * one employee may belong to the same organization.</p>
292:         *
293:         * <p>The most convenient way to access the employees in a given organization
294:         * is by using a sub-index.  For example:</p>
295:         *
296:         * <pre class="code">
297:         * {@code EntityIndex<Long,Entity>} subIndex = employeeByOrganization.subIndex(myOrg);
298:         * {@code EntityCursor<Employee>} cursor = subIndex.entities();
299:         * try {
300:         *     for (Employee entity : cursor) {
301:         *         // Do something with the entity...
302:         *     }
303:         * } finally {
304:         *     cursor.close();
305:         * }</pre>
306:         *
307:         * <p>The secondary key field for a {@link Relationship#MANY_TO_MANY
308:         * MANY_TO_MANY} relationship must be an array or collection type.  To access
309:         * the organizations of an employee, simply access the collection field
310:         * directly.  For example:</p>
311:         *
312:         * <pre class="code">
313:         * Employee employee = primaryIndex.get(1); // Get the entity by primary key
314:         * employee.organizations.remove(myOldOrg); // Remove an organization
315:         * primaryIndex.putNoReturn(1, employee);   // Update the entity</pre>
316:         *
317:         * <h3>Foreign Key Constraints for Related Entities</h3>
318:         *
319:         * <p>In all the examples above the secondary key is treated only as a simple
320:         * value, such as a {@code String} department field.  In many cases, that is
321:         * sufficient.  But in other cases, you may wish to constrain the secondary
322:         * keys of one entity class to be valid primary keys of another entity
323:         * class.  For example, a Department entity may also be defined:</p>
324:         *
325:         * <pre class="code">
326:         * {@literal @Entity}
327:         * class Department {
328:         *
329:         *     {@literal @PrimaryKey}
330:         *     String name;
331:         *
332:         *     String missionStatement;
333:         *
334:         *     private Department() {}
335:         * }</pre>
336:         *
337:         * <p>You may wish to constrain the department field values of the Employee
338:         * class in the examples above to be valid primary keys of the Department
339:         * entity class.  In other words, you may wish to ensure that the department
340:         * field of an Employee will always refer to a valid Department entity.</p>
341:         *
342:         * <p>You can implement this constraint yourself by validating the department
343:         * field before you store an Employee.  For example:</p>
344:         *
345:         * <pre class="code">
346:         * {@code PrimaryIndex<String,Department>} departmentIndex =
347:         *     store.getPrimaryIndex(String.class, Department.class);
348:         *
349:         * void storeEmployee(Employee employee) throws DatabaseException {
350:         *     if (departmentIndex.contains(employee.department)) {
351:         *         primaryIndex.putNoReturn(employee);
352:         *     } else {
353:         *         throw new IllegalArgumentException("Department does not exist: " +
354:         *                                            employee.department);
355:         *     }
356:         * }</pre>
357:         *
358:         * <p>Or, instead you could define the Employee department field as a foreign
359:         * key, and this validation will be done for you when you attempt to store the
360:         * Employee entity.  For example:</p>
361:         *
362:         * <pre class="code">
363:         * {@literal @Entity}
364:         * class Employee {
365:         *
366:         *     {@literal @PrimaryKey}
367:         *     long id;
368:         *
369:         *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Department.class)}
370:         *     String department;
371:         *
372:         *     String name;
373:         *
374:         *     private Employee() {}
375:         * }</pre>
376:         *
377:         * <p>The {@code relatedEntity=Department.class} above defines the department
378:         * field as a foreign key that refers to a Department entity.  Whenever a
379:         * Employee entity is stored, its department field value will be checked to
380:         * ensure that a Department entity exists with that value as its primary key.
381:         * If no such Department entity exists, then a {@link DatabaseException} is
382:         * thrown, causing the transaction to be aborted (assuming that transactions
383:         * are used).</p>
384:         *
385:         * <p>This begs the question:  What happens when a Department entity is deleted
386:         * while one or more Employee entities have department fields that refer to
387:         * the deleted department's primary key?  If the department were allowed to be
388:         * deleted, the foreign key constraint for the Employee department field would
389:         * be violated, because the Employee department field would refer to a
390:         * department that does not exist.</p>
391:         *
392:         * <p>By default, when this situation arises the system does not allow the
393:         * department to be deleted.  Instead, a {@link DatabaseException} is thrown,
394:         * causing the transaction to be aborted.  In this case, in order to delete a
395:         * department, the department field of all Employee entities must first be
396:         * updated to refer to a different existing department, or set to null.  This
397:         * is the responsibility of the application.</p>
398:         *
399:         * <p>There are two additional ways of handling deletion of a Department
400:         * entity.  These alternatives are configured using the {@link
401:         * SecondaryKey#onRelatedEntityDelete} annotation property.  Setting this
402:         * property to {@link DeleteAction#NULLIFY} causes the Employee department
403:         * field to be automatically set to null when the department they refer to is
404:         * deleted.  This may or may not be desirable, depending on application
405:         * policies.  For example:</p>
406:         *
407:         * <pre class="code">
408:         * {@literal @Entity}
409:         * class Employee {
410:         *
411:         *     {@literal @PrimaryKey}
412:         *     long id;
413:         *
414:         *     {@code @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Department.class,
415:         *                                       onRelatedEntityDelete=NULLIFY)}
416:         *     String department;
417:         *
418:         *     String name;
419:         *
420:         *     private Employee() {}
421:         * }</pre>
422:         *
423:         * <p>The {@link DeleteAction#CASCADE} value, on the other hand, causes the
424:         * Employee entities to be automatically deleted when the department they refer
425:         * to is deleted.  This is probably not desirable in this particular example,
426:         * but is useful for parent-child relationships.  For example:</p>
427:         *
428:         * <pre class="code">
429:         * {@literal @Entity}
430:         * class Order {
431:         *
432:         *     {@literal @PrimaryKey}
433:         *     long id;
434:         *
435:         *     String description;
436:         *
437:         *     private Order() {}
438:         * }
439:         *
440:         * {@literal @Entity}
441:         * class OrderItem {
442:         *
443:         *     {@literal @PrimaryKey}
444:         *     long id;
445:         *
446:         *     {@code @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Order.class,
447:         *                                       onRelatedEntityDelete=CASCADE)}
448:         *     long orderId;
449:         *
450:         *     String description;
451:         *
452:         *     private OrderItem() {}
453:         * }</pre>
454:         *
455:         * <p>The OrderItem orderId field refers to its "parent" Order entity.  When an
456:         * Order entity is deleted, it may be useful to automatically delete its
457:         * "child" OrderItem entities.</p>
458:         *
459:         * <p>For more information, see {@link SecondaryKey#onRelatedEntityDelete}.</p>
460:         *
461:         * <h3>One-to-Many versus Many-to-One for Related Entities</h3>
462:         *
463:         * <p>When there is a conceptual Many-to-One relationship such as Employee to
464:         * Department as illustrated in the examples above, the relationship may be
465:         * implemented either as Many-to-One in the Employee class or as One-to-Many in
466:         * the Department class.</p>
467:         *
468:         * <p>Here is the Many-to-One approach.</p>
469:         *
470:         * <pre class="code">
471:         * {@literal @Entity}
472:         * class Employee {
473:         *
474:         *     {@literal @PrimaryKey}
475:         *     long id;
476:         *
477:         *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Department.class)}
478:         *     String department;
479:         *
480:         *     String name;
481:         *
482:         *     private Employee() {}
483:         * }
484:         *
485:         * {@literal @Entity}
486:         * class Department {
487:         *
488:         *     {@literal @PrimaryKey}
489:         *     String name;
490:         *
491:         *     String missionStatement;
492:         *
493:         *     private Department() {}
494:         * }</pre>
495:         *
496:         * <p>And here is the One-to-Many approach.</p>
497:         *
498:         * <pre class="code">
499:         * {@literal @Entity}
500:         * class Employee {
501:         *
502:         *     {@literal @PrimaryKey}
503:         *     long id;
504:         *
505:         *     String name;
506:         *
507:         *     private Employee() {}
508:         * }
509:         *
510:         * {@literal @Entity}
511:         * class Department {
512:         *
513:         *     {@literal @PrimaryKey}
514:         *     String name;
515:         *
516:         *     String missionStatement;
517:         *
518:         *     {@literal @SecondaryKey(relate=ONE_TO_MANY, relatedEntity=Employee.class)}
519:         *     {@literal Set<Long> employees = new HashSet<Long>;}
520:         *
521:         *     private Department() {}
522:         * }</pre>
523:         *
524:         * <p>Which approach is best?  The Many-to-One approach better handles large
525:         * number of entities on the to-Many side of the relationship because it
526:         * doesn't store a collection of keys as an entity field.  With Many-to-One a
527:         * Btree is used to store the collection of keys and the Btree can easily
528:         * handle very large numbers of keys.  With One-to-Many, each time a related
529:         * key is added or removed the entity on the One side of the relationship,
530:         * along with the complete collection of related keys, must be updated.
531:         * Therefore, if large numbers of keys may be stored per relationship,
532:         * Many-to-One is recommended.</p>
533:         *
534:         * <p>If the number of entities per relationship is not a concern, then you may
535:         * wish to choose the approach that is most natural in your application data
536:         * model.  For example, if you think of a Department as containing employees
537:         * and you wish to modify the Department object each time an employee is added
538:         * or removed, then you may wish to store a collection of Employee keys in the
539:         * Department object (One-to-Many).</p>
540:         *
541:         * <p>Note that if you have a One-to-Many relationship and there is no related
542:         * entity, then you don't have a choice -- you have to use One-to-Many because
543:         * there is no entity on the to-Many side of the relationship where a
544:         * Many-to-One key could be defined.  An example is the Employee to email
545:         * addresses relationship discussed above:</p>
546:         *
547:         * <pre class="code">
548:         * {@literal @Entity}
549:         * class Employee {
550:         *
551:         *     {@literal @PrimaryKey}
552:         *     long id;
553:         *
554:         *     {@literal @SecondaryKey(relate=ONE_TO_MANY)}
555:         *     {@literal Set<String> emailAddresses = new HashSet<String>;}
556:         *
557:         *     String name;
558:         *
559:         *     private Employee() {}
560:         * }</pre>
561:         *
562:         * <p>For sake of argument imagine that each employee has thousands of email
563:         * addresses and employees frequently add and remove email addresses.  To
564:         * avoid the potential performance problems associated with updating the
565:         * Employee entity every time an email address is added or removed, you could
566:         * create an EmployeeEmailAddress entity and use a Many-to-One relationship as
567:         * shown below:</p>
568:         *
569:         * <pre class="code">
570:         * {@literal @Entity}
571:         * class Employee {
572:         *
573:         *     {@literal @PrimaryKey}
574:         *     long id;
575:         *
576:         *     String name;
577:         *
578:         *     private Employee() {}
579:         * }
580:         *
581:         * {@literal @Entity}
582:         * class EmployeeEmailAddress {
583:         *
584:         *     {@literal @PrimaryKey}
585:         *     String emailAddress;
586:         *
587:         *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Employee.class)}
588:         *     long employeeId;
589:         *
590:         *     private EmployeeEmailAddress() {}
591:         * }</pre>
592:         *
593:         * <h3>Key Placement with Many-to-Many for Related Entities</h3>
594:         *
595:         * <p>As discussed in the section above, one drawback of a to-Many relationship
596:         * (One-to-Many was discussed above and Many-to-Many is discussed here) is that
597:         * it requires storing a collection of keys in an entity.  Each time a key is
598:         * added or removed, the containing entity must be updated.  This has potential
599:         * performance problems when there are large numbers of entities on the to-Many
600:         * side of the relationship, in other words, when there are large numbers of
601:         * keys in each secondary key field collection.</p>
602:         *
603:         * <p>If you have a Many-to-Many relationship with a reasonably small number of
604:         * entities on one side of the relationship and a large number of entities on
605:         * the other side, you can avoid the potential performance problems by defining
606:         * the secondary key field on the side with a small number of entities.</p>
607:         *
608:         * <p>For example, in an Employee-to-Organization relationship, the number of
609:         * organizations per employee will normally be reasonably small but the number
610:         * of employees per organization may be very large.  Therefore, to avoid
611:         * potential performance problems, the secondary key field should be defined in
612:         * the Employee class as shown below.</p>
613:         *
614:         * <pre class="code">
615:         * {@literal @Entity}
616:         * class Employee {
617:         *
618:         *     {@literal @PrimaryKey}
619:         *     long id;
620:         *
621:         *     {@literal @SecondaryKey(relate=MANY_TO_MANY, relatedEntity=Organization.class)}
622:         *     {@literal Set<String> organizations = new HashSet<String>;}
623:         *
624:         *     String name;
625:         *
626:         *     private Employee() {}
627:         * }
628:         *
629:         * {@literal @Entity}
630:         * class Organization {
631:         *
632:         *     {@literal @PrimaryKey}
633:         *     String name;
634:         *
635:         *     String description;
636:         * }</pre>
637:         *
638:         * <p>If instead a {@code Set<Long> members} key had been defined in the
639:         * Organization class, this set could potentially have a large number of
640:         * elements and performance problems could result.</p>
641:         *
642:         * <h3>Many-to-Many Versus a Relationship Entity</h3>
643:         *
644:         * <p>If you have a Many-to-Many relationship with a large number of entities
645:         * on <em>both</em> sides of the relationship, you can avoid the potential
646:         * performance problems by using a <em>relationship entity</em>.  A
647:         * relationship entity defines the relationship between two other entities
648:         * using two Many-to-One relationships.</p>
649:         *
650:         * <p>Imagine a relationship between cars and trucks indicating whenever a
651:         * particular truck was passed on the road by a particular car.  A given car
652:         * may pass a large number of trucks and a given truck may be passed by a large
653:         * number of cars.  First look at a Many-to-Many relationship between these two
654:         * entities:</p>
655:         *
656:         * <pre class="code">
657:         * {@literal @Entity}
658:         * class Car {
659:         *
660:         *     {@literal @PrimaryKey}
661:         *     String licenseNumber;
662:         *
663:         *     {@literal @SecondaryKey(relate=MANY_TO_MANY, relatedEntity=Truck.class)}
664:         *     {@literal Set<String> trucksPassed = new HashSet<String>;}
665:         *
666:         *     String color;
667:         *
668:         *     private Car() {}
669:         * }
670:         *
671:         * {@literal @Entity}
672:         * class Truck {
673:         *
674:         *     {@literal @PrimaryKey}
675:         *     String licenseNumber;
676:         *
677:         *     int tons;
678:         *
679:         *     private Truck() {}
680:         * }</pre>
681:         *
682:         * <p>With the Many-to-Many approach above, the {@code trucksPassed} set could
683:         * potentially have a large number of elements and performance problems could
684:         * result.</p>
685:         *
686:         * <p>To apply the relationship entity approach we define a new entity class
687:         * named CarPassedTruck representing a single truck passed by a single car.  We
688:         * remove the secondary key from the Car class and use two secondary keys in
689:         * the CarPassedTruck class instead.</p>
690:         *
691:         * <pre class="code">
692:         * {@literal @Entity}
693:         * class Car {
694:         *
695:         *     {@literal @PrimaryKey}
696:         *     String licenseNumber;
697:         *
698:         *     String color;
699:         *
700:         *     private Car() {}
701:         * }
702:         *
703:         * {@literal @Entity}
704:         * class Truck {
705:         *
706:         *     {@literal @PrimaryKey}
707:         *     String licenseNumber;
708:         *
709:         *     int tons;
710:         *
711:         *     private Truck() {}
712:         * }
713:         *
714:         * {@literal @Entity}
715:         * class CarPassedTruck {
716:         *
717:         *     {@literal @PrimaryKey}
718:         *     long id;
719:         *
720:         *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Car.class)}
721:         *     String carLicense;
722:         *
723:         *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Truck.class)}
724:         *     String truckLicense;
725:         *
726:         *     private CarPassedTruck() {}
727:         * }</pre>
728:         *
729:         * <p>The CarPassedTruck entity can be used to access the relationship by car
730:         * license or by truck license.</p>
731:         *
732:         * <p>You may use the relationship entity approach because of the potential
733:         * performance problems mentioned above.  Or, you may choose to use this
734:         * approach in order to store other information about the relationship.  For
735:         * example, if for each car that passes a truck you wish to record how much
736:         * faster the car was going than the truck, then a relationship entity is the
737:         * logical place to store that property.  In the example below the
738:         * speedDifference property is added to the CarPassedTruck class.</p>
739:         *
740:         * <pre class="code">
741:         * {@literal @Entity}
742:         * class CarPassedTruck {
743:         *
744:         *     {@literal @PrimaryKey}
745:         *     long id;
746:         *
747:         *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Car.class)}
748:         *     String carLicense;
749:         *
750:         *     {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Truck.class)}
751:         *     String truckLicense;
752:         *
753:         *     int speedDifference;
754:         *
755:         *     private CarPassedTruck() {}
756:         * }</pre>
757:         *
758:         * <p>Be aware that the relationship entity approach adds overhead compared to
759:         * Many-to-Many.  There is one additional entity and one additional secondary
760:         * key.  These factors should be weighed against its advantages and the
761:         * relevant application access patterns should be considered.</p>
762:         *
763:         * @author Mark Hayes
764:         */
765:        public class SecondaryIndex<SK, PK, E> extends BasicIndex<SK, E> {
766:
767:            private SecondaryDatabase secDb;
768:            private Database keysDb;
769:            private PrimaryIndex priIndex;
770:            private EntityBinding entityBinding;
771:            private EntityIndex<SK, PK> keysIndex;
772:            private SortedMap<SK, E> map;
773:
774:            /**
775:             * Creates a secondary index without using an <code>EntityStore</code>.
776:             * When using an {@link EntityStore}, call {@link
777:             * EntityStore#getSecondaryIndex getSecondaryIndex} instead.
778:             *
779:             * <p>This constructor is not normally needed and is provided for
780:             * applications that wish to use custom bindings along with the Direct
781:             * Persistence Layer.  Normally, {@link EntityStore#getSecondaryIndex
782:             * getSecondaryIndex} is used instead.</p>
783:             *
784:             * @param database the secondary database used for all access other than
785:             * via a {@link #keysIndex}.
786:             *
787:             * @param keysDatabase another handle on the secondary database, opened
788:             * without association to the primary, and used only for access via a
789:             * {@link #keysIndex}.  If this argument is null and the {@link #keysIndex}
790:             * method is called, then the keys database will be opened automatically;
791:             * however, the user is then responsible for closing the keys database.  To
792:             * get the keys database in order to close it, call {@link
793:             * #getKeysDatabase}.
794:             *
795:             * @param primaryIndex the primary index associated with this secondary
796:             * index.
797:             *
798:             * @param secondaryKeyClass the class of the secondary key.
799:             *
800:             * @param secondaryKeyBinding the binding to be used for secondary keys.
801:             */
802:            public SecondaryIndex(SecondaryDatabase database,
803:                    Database keysDatabase, PrimaryIndex<PK, E> primaryIndex,
804:                    Class<SK> secondaryKeyClass,
805:                    EntryBinding secondaryKeyBinding) throws DatabaseException {
806:
807:                super (database, secondaryKeyClass, secondaryKeyBinding,
808:                        new EntityValueAdapter(primaryIndex.getEntityClass(),
809:                                primaryIndex.getEntityBinding(), true));
810:                secDb = database;
811:                keysDb = keysDatabase;
812:                priIndex = primaryIndex;
813:                entityBinding = primaryIndex.getEntityBinding();
814:            }
815:
816:            /**
817:             * Returns the underlying secondary database for this index.
818:             *
819:             * @return the secondary database.
820:             */
821:            public SecondaryDatabase getDatabase() {
822:                return secDb;
823:            }
824:
825:            /**
826:             * Returns the underlying secondary database that is not associated with
827:             * the primary database and is used for the {@link #keysIndex}.
828:             *
829:             * @return the keys database.
830:             */
831:            public Database getKeysDatabase() {
832:                return keysDb;
833:            }
834:
835:            /**
836:             * Returns the primary index associated with this secondary index.
837:             *
838:             * @return the primary index.
839:             */
840:            public PrimaryIndex<PK, E> getPrimaryIndex() {
841:                return priIndex;
842:            }
843:
844:            /**
845:             * Returns the secondary key class for this index.
846:             *
847:             * @return the class.
848:             */
849:            public Class<SK> getKeyClass() {
850:                return keyClass;
851:            }
852:
853:            /**
854:             * Returns the secondary key binding for the index.
855:             *
856:             * @return the key binding.
857:             */
858:            public EntryBinding getKeyBinding() {
859:                return keyBinding;
860:            }
861:
862:            /**
863:             * Returns a read-only keys index that maps secondary key to primary key.
864:             * When accessing the keys index, the primary key is returned rather than
865:             * the entity.  When only the primary key is needed and not the entire
866:             * entity, using the keys index is less expensive than using the secondary
867:             * index because the primary index does not have to be accessed.
868:             *
869:             * <p>Note the following in the unusual case that you are <em>not</em>
870:             * using an <code>EntityStore</code>: This method will open the keys
871:             * database, a second database handle for the secondary database, if it is
872:             * not already open.  In this case, if you are <em>not</em> using an
873:             * <code>EntityStore</code>, then you are responsible for closing the
874:             * database returned by {@link #getKeysDatabase} before closing the
875:             * environment.  If you <em>are</em> using an <code>EntityStore</code>, the
876:             * keys database will be closed automatically by {@link
877:             * EntityStore#close}.</p>
878:             *
879:             * @return the keys index.
880:             */
881:            public synchronized EntityIndex<SK, PK> keysIndex()
882:                    throws DatabaseException {
883:
884:                if (keysIndex == null) {
885:                    if (keysDb == null) {
886:                        DatabaseConfig config = secDb.getConfig();
887:                        config.setReadOnly(true);
888:                        keysDb = db.getEnvironment().openDatabase(null,
889:                                secDb.getDatabaseName(), config);
890:                    }
891:                    keysIndex = new KeysIndex<SK, PK>(keysDb, keyClass,
892:                            keyBinding, priIndex.getKeyClass(), priIndex
893:                                    .getKeyBinding());
894:                }
895:                return keysIndex;
896:            }
897:
898:            /**
899:             * Returns an index that maps primary key to entity for the subset of
900:             * entities having a given secondary key (duplicates).  A sub-index is
901:             * convenient when you are interested in working with the subset of
902:             * entities having a particular secondary key value.
903:             *
904:             * <p>When using a {@link Relationship#MANY_TO_ONE MANY_TO_ONE} or {@link
905:             * Relationship#MANY_TO_MANY MANY_TO_MANY} secondary key, the sub-index
906:             * represents the left (MANY) side of a relationship.</p>
907:             *
908:             * @param key the secondary key that identifies the entities in the
909:             * sub-index.
910:             *
911:             * @return the sub-index.
912:             */
913:            public EntityIndex<PK, E> subIndex(SK key) throws DatabaseException {
914:
915:                return new SubIndex(this , entityBinding, key);
916:            }
917:
918:            /*
919:             * Of the EntityIndex methods only get()/map()/sortedMap() are implemented
920:             * here.  All other methods are implemented by BasicIndex.
921:             */
922:
923:            public E get(SK key) throws DatabaseException {
924:
925:                return get(null, key, null);
926:            }
927:
928:            public E get(Transaction txn, SK key, LockMode lockMode)
929:                    throws DatabaseException {
930:
931:                DatabaseEntry keyEntry = new DatabaseEntry();
932:                DatabaseEntry pkeyEntry = new DatabaseEntry();
933:                DatabaseEntry dataEntry = new DatabaseEntry();
934:                keyBinding.objectToEntry(key, keyEntry);
935:
936:                OperationStatus status = secDb.get(txn, keyEntry, pkeyEntry,
937:                        dataEntry, lockMode);
938:
939:                if (status == OperationStatus.SUCCESS) {
940:                    return (E) entityBinding
941:                            .entryToObject(pkeyEntry, dataEntry);
942:                } else {
943:                    return null;
944:                }
945:            }
946:
947:            public Map<SK, E> map() {
948:                return sortedMap();
949:            }
950:
951:            public synchronized SortedMap<SK, E> sortedMap() {
952:                if (map == null) {
953:                    map = new StoredSortedMap(db, keyBinding, entityBinding,
954:                            true);
955:                }
956:                return map;
957:            }
958:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.