Source Code Cross Referenced for PrimaryIndex.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: PrimaryIndex.java,v 1.17.2.2 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.Cursor;
018:        import com.sleepycat.je.Database;
019:        import com.sleepycat.je.DatabaseEntry;
020:        import com.sleepycat.je.DatabaseException;
021:        import com.sleepycat.je.Environment;
022:        import com.sleepycat.je.LockMode;
023:        import com.sleepycat.je.OperationStatus;
024:        import com.sleepycat.je.Transaction;
025:        import com.sleepycat.persist.impl.PersistEntityBinding;
026:        import com.sleepycat.persist.impl.PersistKeyAssigner;
027:        import com.sleepycat.persist.model.Entity;
028:        import com.sleepycat.persist.model.PrimaryKey;
029:
030:        /**
031:         * The primary index for an entity class and its primary key.
032:         *
033:         * <p>{@code PrimaryIndex} objects are thread-safe.  Multiple threads may
034:         * safely call the methods of a shared {@code PrimaryIndex} object.</p>
035:         *
036:         * <p>{@code PrimaryIndex} implements {@link EntityIndex} to map the primary
037:         * key type (PK) to the entity type (E).</p>
038:         *
039:         * <p>The {@link Entity} annotation may be used to define an entity class and
040:         * the {@link PrimaryKey} annotation may be used to define a primary key as
041:         * shown in the following example.</p>
042:         *
043:         * <pre class="code">
044:         * {@literal @Entity}
045:         * class Employee {
046:         *
047:         *     {@literal @PrimaryKey}
048:         *     long id;
049:         *
050:         *     String name;
051:         *
052:         *     Employee(long id, String name) {
053:         *         this.id = id;
054:         *         this.name = name;
055:         *     }
056:         *
057:         *     private Employee() {} // For bindings
058:         * }</pre>
059:         *
060:         * <p>To obtain the {@code PrimaryIndex} for a given entity class, call {@link
061:         * EntityStore#getPrimaryIndex EntityStore.getPrimaryIndex}, passing the
062:         * primary key class and the entity class.  For example:</p>
063:         *
064:         * <pre class="code">
065:         * EntityStore store = new EntityStore(...);
066:         *
067:         * {@code PrimaryIndex<Long,Employee>} primaryIndex =
068:         *     store.getPrimaryIndex(Long.class, Employee.class);</pre>
069:         * </pre>
070:         *
071:         * <p>Note that {@code Long.class} is passed as the primary key class, but the
072:         * primary key field has the primitive type {@code long}.  When a primitive
073:         * primary key field is used, the corresponding primitive wrapper class is used
074:         * to access the primary index.  For more information on key field types, see
075:         * {@link PrimaryKey}.</p>
076:         *
077:         * <p>The {@code PrimaryIndex} provides the primary storage and access methods
078:         * for the instances of a particular entity class.  Entities are inserted and
079:         * updated in the {@code PrimaryIndex} by calling a method in the family of
080:         * {@link #put} methods.  The {@link #put} method will insert the entity if no
081:         * entity with the same primary key already exists.  If an entity with the same
082:         * primary key does exist, it will update the entity and return the existing
083:         * (old) entity.  For example:</p>
084:         *
085:         * <pre class="code">
086:         * Employee oldEntity;
087:         * oldEntity = primaryIndex.put(new Employee(1, "Jane Smith"));    // Inserts an entity
088:         * assert oldEntity == null;
089:         * oldEntity = primaryIndex.put(new Employee(2, "Joan Smith"));    // Inserts an entity
090:         * assert oldEntity == null;
091:         * oldEntity = primaryIndex.put(new Employee(2, "Joan M. Smith")); // Updates an entity
092:         * assert oldEntity != null;</pre>
093:         *
094:         * <p>The {@link #putNoReturn} method can be used to avoid the overhead of
095:         * returning the existing entity, when the existing entity is not important to
096:         * the application.  The return type of {@link #putNoReturn} is void.  For
097:         * example:</p>
098:         *
099:         * <pre class="code">
100:         * primaryIndex.putNoReturn(new Employee(1, "Jane Smith"));    // Inserts an entity
101:         * primaryIndex.putNoReturn(new Employee(2, "Joan Smith"));    // Inserts an entity
102:         * primaryIndex.putNoReturn(new Employee(2, "Joan M. Smith")); // Updates an entity</pre>
103:         *
104:         * <p>The {@link #putNoOverwrite} method can be used to ensure that an existing
105:         * entity is not overwritten.  {@link #putNoOverwrite} returns true if the
106:         * entity was inserted, or false if an existing entity exists and no action was
107:         * taken.  For example:<p>
108:         *
109:         * <pre class="code">
110:         * boolean inserted;
111:         * inserted = primaryIndex.putNoOverwrite(new Employee(1, "Jane Smith"));    // Inserts an entity
112:         * assert inserted;
113:         * inserted = primaryIndex.putNoOverwrite(new Employee(2, "Joan Smith"));    // Inserts an entity
114:         * assert inserted;
115:         * inserted = primaryIndex.putNoOverwrite(new Employee(2, "Joan M. Smith")); // <strong>No action was taken!</strong>
116:         * assert !inserted;</pre>
117:         *
118:         * <p>Primary key values must be unique, in other words, each instance of a
119:         * given entity class must have a distinct primary key value.  Rather than
120:         * assigning the unique primary key values yourself, a <em>sequence</em> can be
121:         * used to assign sequential integer values automatically, starting with the
122:         * value 1 (one).  A sequence is defined using the {@link PrimaryKey#sequence}
123:         * annotation property.  For example:</p>
124:         *
125:         * <pre class="code">
126:         * {@literal @Entity}
127:         * class Employee {
128:         *
129:         *     {@literal @PrimaryKey(sequence="ID")}
130:         *     long id;
131:         *
132:         *     String name;
133:         *
134:         *     Employee(String name) {
135:         *         this.name = name;
136:         *     }
137:         *
138:         *     private Employee() {} // For bindings
139:         * }</pre>
140:         *
141:         * <p>The name of the sequence used above is "ID".  Any name can be used.  If
142:         * the same sequence name is used in more than one entity class, the sequence
143:         * will be shared by those classes, in other words, a single sequence of
144:         * integers will be used for all instances of those classes.  See {@link
145:         * PrimaryKey#sequence} for more information.</p>
146:         *
147:         * <p>Any method in the family of {@link #put} methods may be used to insert
148:         * entities where the primary key is assigned from a sequence.  When the {@link
149:         * #put} method returns, the primary key field of the entity object will be set
150:         * to the assigned key value.  For example:</p>
151:         *
152:         * <pre class="code">
153:         * Employee employee;
154:         * employee = new Employee("Jane Smith");
155:         * primaryIndex.putNoReturn(employee);    // Inserts an entity
156:         * assert employee.id == 1;
157:         * employee = new Employee("Joan Smith");
158:         * primaryIndex.putNoReturn(employee);    // Inserts an entity
159:         * assert employee.id == 2;</pre>
160:         *
161:         * <p>This begs the question:  How do you update an existing entity, without
162:         * assigning a new primary key?  The answer is that the {@link #put} methods
163:         * will only assign a new key from the sequence if the primary key field is
164:         * zero or null (for reference types).  If an entity with a non-zero and
165:         * non-null key field is passed to a {@link #put} method, any existing entity
166:         * with that primary key value will be updated.  For example:</p>
167:         *
168:         * <pre class="code">
169:         * Employee employee;
170:         * employee = new Employee("Jane Smith");
171:         * primaryIndex.putNoReturn(employee);    // Inserts an entity
172:         * assert employee.id == 1;
173:         * employee = new Employee("Joan Smith");
174:         * primaryIndex.putNoReturn(employee);    // Inserts an entity
175:         * assert employee.id == 2;
176:         * employee.name = "Joan M. Smith";
177:         * primaryIndex.putNoReturn(employee);    // Updates an existing entity
178:         * assert employee.id == 2;</pre>
179:         *
180:         * <p>Since {@code PrimaryIndex} implements the {@link EntityIndex} interface,
181:         * it shares the common index methods for retrieving and deleting entities,
182:         * opening cursors and using transactions.  See {@link EntityIndex} for more
183:         * information on these topics.</p>
184:         *
185:         * <p>Note that when using an index, keys and values are stored and retrieved
186:         * by value not by reference.  In other words, if an entity object is stored
187:         * and then retrieved, or retrieved twice, each object will be a separate
188:         * instance.  For example, in the code below the assertion will always
189:         * fail.</p>
190:         * <pre class="code">
191:         * MyKey key = ...;
192:         * MyEntity entity1 = new MyEntity(key, ...);
193:         * index.put(entity1);
194:         * MyEntity entity2 = index.get(key);
195:         * assert entity1 == entity2; // always fails!
196:         * </pre>
197:         *
198:         * @author Mark Hayes
199:         */
200:        public class PrimaryIndex<PK, E> extends BasicIndex<PK, E> {
201:
202:            private Class<E> entityClass;
203:            private EntityBinding entityBinding;
204:            private SortedMap<PK, E> map;
205:            private PersistKeyAssigner keyAssigner;
206:
207:            /**
208:             * Creates a primary index without using an <code>EntityStore</code>.
209:             *
210:             * <p>This constructor is not normally needed and is provided for
211:             * applications that wish to use custom bindings along with the Direct
212:             * Persistence Layer.  Normally, {@link EntityStore#getPrimaryIndex
213:             * getPrimaryIndex} is used instead.</p>
214:             *
215:             * <p>Note that when this constructor is used directly, primary keys cannot
216:             * be automatically assigned from a sequence.  The key assignment feature
217:             * requires knowledge of the primary key field, which is only available if
218:             * an <code>EntityStore</code> is used.  Of course, primary keys may be
219:             * assigned from a sequence manually before calling the <code>put</code>
220:             * methods in this class.</p>
221:             *
222:             * @param database the primary database.
223:             *
224:             * @param keyClass the class of the primary key.
225:             *
226:             * @param keyBinding the binding to be used for primary keys.
227:             *
228:             * @param entityClass the class of the entities stored in this index.
229:             *
230:             * @param entityBinding the binding to be used for entities.
231:             */
232:            public PrimaryIndex(Database database, Class<PK> keyClass,
233:                    EntryBinding keyBinding, Class<E> entityClass,
234:                    EntityBinding entityBinding) throws DatabaseException {
235:
236:                super (database, keyClass, keyBinding, new EntityValueAdapter(
237:                        entityClass, entityBinding, false));
238:
239:                this .entityClass = entityClass;
240:                this .entityBinding = entityBinding;
241:
242:                if (entityBinding instanceof  PersistEntityBinding) {
243:                    keyAssigner = ((PersistEntityBinding) entityBinding)
244:                            .getKeyAssigner();
245:                }
246:            }
247:
248:            /**
249:             * Returns the underlying database for this index.
250:             *
251:             * @return the database.
252:             */
253:            public Database getDatabase() {
254:                return db;
255:            }
256:
257:            /**
258:             * Returns the primary key class for this index.
259:             *
260:             * @return the key class.
261:             */
262:            public Class<PK> getKeyClass() {
263:                return keyClass;
264:            }
265:
266:            /**
267:             * Returns the primary key binding for this index.
268:             *
269:             * @return the key binding.
270:             */
271:            public EntryBinding getKeyBinding() {
272:                return keyBinding;
273:            }
274:
275:            /**
276:             * Returns the entity class for this index.
277:             *
278:             * @return the entity class.
279:             */
280:            public Class<E> getEntityClass() {
281:                return entityClass;
282:            }
283:
284:            /**
285:             * Returns the entity binding for this index.
286:             *
287:             * @return the entity binding.
288:             */
289:            public EntityBinding getEntityBinding() {
290:                return entityBinding;
291:            }
292:
293:            /**
294:             * Inserts an entity and returns null, or updates it if the primary key
295:             * already exists and returns the existing entity.
296:             *
297:             * <p>If a {@link PrimaryKey#sequence} is used and the primary key field of
298:             * the given entity is null or zero, this method will assign the next value
299:             * from the sequence to the primary key field of the given entity.</p>
300:             *
301:             * <p>Auto-commit is used implicitly if the store is transactional.</p>
302:             *
303:             * @param entity the entity to be inserted or updated.
304:             *
305:             * @return the existing entity that was updated, or null if the entity was
306:             * inserted.
307:             */
308:            public E put(E entity) throws DatabaseException {
309:
310:                return put(null, entity);
311:            }
312:
313:            /**
314:             * Inserts an entity and returns null, or updates it if the primary key
315:             * already exists and returns the existing entity.
316:             *
317:             * <p>If a {@link PrimaryKey#sequence} is used and the primary key field of
318:             * the given entity is null or zero, this method will assign the next value
319:             * from the sequence to the primary key field of the given entity.</p>
320:             *
321:             * @param txn the transaction used to protect this operation, null to use
322:             * auto-commit, or null if the store is non-transactional.
323:             *
324:             * @param entity the entity to be inserted or updated.
325:             *
326:             * @return the existing entity that was updated, or null if the entity was
327:             * inserted.
328:             */
329:            public E put(Transaction txn, E entity) throws DatabaseException {
330:
331:                DatabaseEntry keyEntry = new DatabaseEntry();
332:                DatabaseEntry dataEntry = new DatabaseEntry();
333:                assignKey(entity, keyEntry);
334:
335:                boolean autoCommit = false;
336:                Environment env = db.getEnvironment();
337:                if (transactional && txn == null
338:                        && env.getThreadTransaction() == null) {
339:                    txn = env.beginTransaction(null, null);
340:                    autoCommit = true;
341:                }
342:
343:                boolean failed = true;
344:                Cursor cursor = db.openCursor(txn, null);
345:                try {
346:                    while (true) {
347:                        OperationStatus status = cursor.getSearchKey(keyEntry,
348:                                dataEntry, LockMode.RMW);
349:                        if (status == OperationStatus.SUCCESS) {
350:                            E existing = (E) entityBinding.entryToObject(
351:                                    keyEntry, dataEntry);
352:                            entityBinding.objectToData(entity, dataEntry);
353:                            cursor.put(keyEntry, dataEntry);
354:                            failed = false;
355:                            return existing;
356:                        } else {
357:                            entityBinding.objectToData(entity, dataEntry);
358:                            status = cursor.putNoOverwrite(keyEntry, dataEntry);
359:                            if (status != OperationStatus.KEYEXIST) {
360:                                failed = false;
361:                                return null;
362:                            }
363:                        }
364:                    }
365:                } finally {
366:                    cursor.close();
367:                    if (autoCommit) {
368:                        if (failed) {
369:                            txn.abort();
370:                        } else {
371:                            txn.commit();
372:                        }
373:                    }
374:                }
375:            }
376:
377:            /**
378:             * Inserts an entity, or updates it if the primary key already exists (does
379:             * not return the existing entity).  This method may be used instead of
380:             * {@link #put(Object)} to save the overhead of returning the existing
381:             * entity.
382:             *
383:             * <p>If a {@link PrimaryKey#sequence} is used and the primary key field of
384:             * the given entity is null or zero, this method will assign the next value
385:             * from the sequence to the primary key field of the given entity.</p>
386:             *
387:             * <p>Auto-commit is used implicitly if the store is transactional.</p>
388:             *
389:             * @param entity the entity to be inserted or updated.
390:             */
391:            public void putNoReturn(E entity) throws DatabaseException {
392:
393:                putNoReturn(null, entity);
394:            }
395:
396:            /**
397:             * Inserts an entity, or updates it if the primary key already exists (does
398:             * not return the existing entity).  This method may be used instead of
399:             * {@link #put(Transaction,Object)} to save the overhead of returning the
400:             * existing entity.
401:             *
402:             * <p>If a {@link PrimaryKey#sequence} is used and the primary key field of
403:             * the given entity is null or zero, this method will assign the next value
404:             * from the sequence to the primary key field of the given entity.</p>
405:             *
406:             * @param txn the transaction used to protect this operation, null to use
407:             * auto-commit, or null if the store is non-transactional.
408:             *
409:             * @param entity the entity to be inserted or updated.
410:             */
411:            public void putNoReturn(Transaction txn, E entity)
412:                    throws DatabaseException {
413:
414:                DatabaseEntry keyEntry = new DatabaseEntry();
415:                DatabaseEntry dataEntry = new DatabaseEntry();
416:                assignKey(entity, keyEntry);
417:                entityBinding.objectToData(entity, dataEntry);
418:
419:                db.put(txn, keyEntry, dataEntry);
420:            }
421:
422:            /**
423:             * Inserts an entity and returns true, or returns false if the primary key
424:             * already exists.
425:             *
426:             * <p>If a {@link PrimaryKey#sequence} is used and the primary key field of
427:             * the given entity is null or zero, this method will assign the next value
428:             * from the sequence to the primary key field of the given entity.</p>
429:             *
430:             * <p>Auto-commit is used implicitly if the store is transactional.</p>
431:             *
432:             * @param entity the entity to be inserted.
433:             *
434:             * @return true if the entity was inserted, or false if an entity with the
435:             * same primary key is already present.
436:             */
437:            public boolean putNoOverwrite(E entity) throws DatabaseException {
438:
439:                return putNoOverwrite(null, entity);
440:            }
441:
442:            /**
443:             * Inserts an entity and returns true, or returns false if the primary key
444:             * already exists.
445:             *
446:             * <p>If a {@link PrimaryKey#sequence} is used and the primary key field of
447:             * the given entity is null or zero, this method will assign the next value
448:             * from the sequence to the primary key field of the given entity.</p>
449:             *
450:             * @param txn the transaction used to protect this operation, null to use
451:             * auto-commit, or null if the store is non-transactional.
452:             *
453:             * @param entity the entity to be inserted.
454:             *
455:             * @return true if the entity was inserted, or false if an entity with the
456:             * same primary key is already present.
457:             */
458:            public boolean putNoOverwrite(Transaction txn, E entity)
459:                    throws DatabaseException {
460:
461:                DatabaseEntry keyEntry = new DatabaseEntry();
462:                DatabaseEntry dataEntry = new DatabaseEntry();
463:                assignKey(entity, keyEntry);
464:                entityBinding.objectToData(entity, dataEntry);
465:
466:                OperationStatus status = db.putNoOverwrite(txn, keyEntry,
467:                        dataEntry);
468:
469:                return (status == OperationStatus.SUCCESS);
470:            }
471:
472:            /**
473:             * If we are assigning primary keys from a sequence, assign the next key
474:             * and set the primary key field.
475:             */
476:            private void assignKey(E entity, DatabaseEntry keyEntry)
477:                    throws DatabaseException {
478:
479:                if (keyAssigner != null) {
480:                    if (!keyAssigner.assignPrimaryKey(entity, keyEntry)) {
481:                        entityBinding.objectToKey(entity, keyEntry);
482:                    }
483:                } else {
484:                    entityBinding.objectToKey(entity, keyEntry);
485:                }
486:            }
487:
488:            /*
489:             * Of the EntityIndex methods only get()/map()/sortedMap() are implemented
490:             * here.  All other methods are implemented by BasicIndex.
491:             */
492:
493:            public E get(PK key) throws DatabaseException {
494:
495:                return get(null, key, null);
496:            }
497:
498:            public E get(Transaction txn, PK key, LockMode lockMode)
499:                    throws DatabaseException {
500:
501:                DatabaseEntry keyEntry = new DatabaseEntry();
502:                DatabaseEntry dataEntry = new DatabaseEntry();
503:                keyBinding.objectToEntry(key, keyEntry);
504:
505:                OperationStatus status = db.get(txn, keyEntry, dataEntry,
506:                        lockMode);
507:
508:                if (status == OperationStatus.SUCCESS) {
509:                    return (E) entityBinding.entryToObject(keyEntry, dataEntry);
510:                } else {
511:                    return null;
512:                }
513:            }
514:
515:            public Map<PK, E> map() {
516:                return sortedMap();
517:            }
518:
519:            public synchronized SortedMap<PK, E> sortedMap() {
520:                if (map == null) {
521:                    map = new StoredSortedMap(db, keyBinding, entityBinding,
522:                            true);
523:                }
524:                return map;
525:            }
526:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.