Source Code Cross Referenced for KeyGenerator.java in  » Database-ORM » ProjectJulp » org » julp » 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 » Database ORM » ProjectJulp » org.julp 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:            CREATE TABLE SEQUENCES(
003:                SEQUENCE_ID VARCHAR(30) NOT NULL,
004:                ID INTEGER NOT NULL,
005:                CONSTRAINT PK_SEQUENCE PRIMARY KEY(SEQUENCE_ID)
006:            );
007:         
008:            INSERT INTO SEQUENCES VALUES('MY_SEQUENCE', 0); // FOR EACH TABLE...
009:         
010:            -HIGH/LOW ID pattern implementation-
011:         */
012:
013:        package org.julp;
014:
015:        import java.lang.reflect.Constructor;
016:        import java.lang.reflect.InvocationTargetException;
017:        import java.sql.SQLException;
018:        import java.util.ArrayList;
019:        import java.util.Collection;
020:        import java.util.HashMap;
021:        import java.util.Map;
022:        import java.math.BigInteger;
023:        import java.math.BigDecimal;
024:        import java.util.Collections;
025:        import java.util.Set;
026:        import java.util.HashSet;
027:
028:        public class KeyGenerator {
029:
030:            protected String table; // required
031:            protected String idColumn; // required
032:            protected String sequenceNameColumn; // required for non-externalSequence
033:            protected int increment = 10; // any number greater than zero
034:            /** DO NOT USE THE SAME CONNECTION AS THE REST OF THE APPLICATION SINCE CONNECTION FOR KeyGenerator COMMITS ALWAYS!!! */
035:            protected DBServices dbServices;
036:            protected int retryMax = 3; // any number greater than zero
037:            protected long timeout = 250; // any number greater than zero
038:            protected String sqlState = "23000"; // SQLSTATE - duplicate key
039:            protected int vendorErrorCode = Integer.MIN_VALUE;
040:            protected int isolationLevel = -1;
041:            protected boolean isolationLevelSet = false;
042:            protected Map lowValues = Collections
043:                    .synchronizedMap(new HashMap());
044:            protected Map hiValues = Collections.synchronizedMap(new HashMap());
045:            protected Class keyClass = Integer.class; // any class which extends java.lang.Number
046:            protected boolean externalSequence = false; // used with "real" sequences: Oracle, PostgreSQL, etc...
047:            protected String select;
048:            protected String update;
049:            protected String insert; // if not exists automatically creates new sequence upon request
050:            protected boolean createSequenceOnDemand = true;
051:            protected Number initialValue = new Integer(0); // not used with "real" sequences
052:            protected Set sequences;
053:            protected boolean cacheStatements;
054:
055:            public KeyGenerator() {
056:            }
057:
058:            public KeyGenerator(int isolationLevel) {
059:                this .isolationLevel = isolationLevel;
060:            }
061:
062:            public KeyGenerator(String table, String sequenceNameColumn,
063:                    String idColumn, int isolationLevel) {
064:                this .table = table;
065:                this .sequenceNameColumn = sequenceNameColumn;
066:                this .idColumn = idColumn;
067:                this .isolationLevel = isolationLevel;
068:            }
069:
070:            public KeyGenerator(String table, String sequenceNameColumn,
071:                    String idColumn) {
072:                this .table = table;
073:                this .sequenceNameColumn = sequenceNameColumn;
074:                this .idColumn = idColumn;
075:            }
076:
077:            public KeyGenerator(String table, String sequenceNameColumn,
078:                    String idColumn, int isolationLevel,
079:                    boolean externalSequence) {
080:                this .table = table;
081:                this .sequenceNameColumn = sequenceNameColumn;
082:                this .idColumn = idColumn;
083:                this .isolationLevel = isolationLevel;
084:                this .externalSequence = externalSequence;
085:            }
086:
087:            public KeyGenerator(String table, String sequenceNameColumn,
088:                    String idColumn, boolean externalSequence) {
089:                this .table = table;
090:                this .sequenceNameColumn = sequenceNameColumn;
091:                this .idColumn = idColumn;
092:                this .externalSequence = externalSequence;
093:            }
094:
095:            public void init() {
096:                if (!externalSequence && this .table == null) {
097:                    throw new IllegalStateException("Table name is missing");
098:                }
099:                if (!externalSequence && this .sequenceNameColumn == null) {
100:                    throw new IllegalStateException(
101:                            "Sequence column name is missing");
102:                }
103:                if (this .idColumn == null) {
104:                    throw new IllegalStateException("ID column name is missing");
105:                }
106:                if (dbServices == null) {
107:                    throw new IllegalStateException("DBServices not set");
108:                }
109:                if (!externalSequence) {
110:                    // SELECT ID FROM SEQUENCES WHERE SEQUENCE_NAME = ? ${sequence}
111:                    select = "SELECT " + idColumn + " FROM " + table
112:                            + " WHERE " + sequenceNameColumn + " = ?";
113:                    // UPDATE SEQUENCES SET ID = ID + 10 WHERE SEQUENCE_NAME = ? AND ID = ? ${current ID}
114:                    update = "UPDATE " + table + " SET " + idColumn + " = "
115:                            + idColumn + " + " + String.valueOf(increment)
116:                            + " WHERE " + sequenceNameColumn + " = ? AND "
117:                            + idColumn + " = ?";
118:                    if (createSequenceOnDemand) {
119:                        // INSERT INTO SEQUENCES (SEQUENCE_NAME, ID) VALUES (?, 0) ${sequence}
120:                        insert = "INSERT INTO " + table + " ("
121:                                + sequenceNameColumn + ", " + idColumn
122:                                + ") VALUES (?, " + initialValue.toString()
123:                                + ")";
124:                    }
125:                    String allSequences = "SELECT " + sequenceNameColumn
126:                            + " FROM " + table;
127:                    try {
128:                        sequences = Collections
129:                                .synchronizedSet(new HashSet(
130:                                        dbServices
131:                                                .getSingleColumnResultAsList(allSequences)));
132:                    } catch (SQLException sqle) {
133:                        throw new RuntimeException(sqle);
134:                    }
135:                }
136:            }
137:
138:            public synchronized Number getNextValue(String sequence)
139:                    throws SQLException {
140:                if (!externalSequence && this .select == null) {
141:                    throw new IllegalStateException(
142:                            "KeyGenerator not initialized");
143:                }
144:                if (!externalSequence && !sequences.contains(sequence)
145:                        && createSequenceOnDemand) { // new sequence
146:                    Collection param = new ArrayList(1);
147:                    param.add(sequence);
148:                    dbServices.execute(insert, param);
149:                    sequences.add(sequence);
150:                }
151:                Object value = lowValues.get(sequenceNameColumn);
152:                Number hiValue = null;
153:                if (value == null) {
154:                    value = getSeed(sequence);
155:                    lowValues.put(sequenceNameColumn, value);
156:                    if (keyClass.getName().equals("java.lang.Integer")) {
157:                        hiValue = ((Number) value).intValue() + increment;
158:                    } else if (keyClass.getName().equals("java.lang.Long")) {
159:                        hiValue = ((Number) value).longValue() + increment;
160:                    } else if (keyClass.getName()
161:                            .equals("java.math.BigInteger")) {
162:                        hiValue = new BigInteger(value.toString())
163:                                .add(new BigInteger(String.valueOf(increment)));
164:                    } else if (keyClass.getName()
165:                            .equals("java.math.BigDecimal")) {
166:                        hiValue = new BigDecimal(value.toString())
167:                                .add(new BigDecimal(String.valueOf(increment)));
168:                    } else {
169:                        try {
170:                            hiValue = new BigDecimal(value.toString())
171:                                    .add(new BigDecimal(String
172:                                            .valueOf(increment)));
173:                            Constructor c = keyClass
174:                                    .getConstructor(String.class);
175:                            hiValue = (Number) c
176:                                    .newInstance(hiValue.toString());
177:                        } catch (InvocationTargetException ite) {
178:                            throw new SQLException(ite.getTargetException()
179:                                    .toString());
180:                        } catch (Exception e) {
181:                            throw new SQLException(e.toString());
182:                        }
183:                    }
184:                    hiValues.put(sequenceNameColumn, hiValue);
185:                } else {
186:                    if (keyClass.getName().equals("java.lang.Integer")) {
187:                        if (((Number) value).intValue() < ((Number) hiValues
188:                                .get(sequenceNameColumn)).intValue() - 1) {
189:                            value = new Integer(((Number) value).intValue() + 1);
190:                            lowValues.put(sequenceNameColumn, value);
191:                        } else {
192:                            value = getSeed(sequence);
193:                            lowValues.put(sequenceNameColumn, value);
194:                            hiValues.put(sequenceNameColumn, ((Number) value)
195:                                    .intValue()
196:                                    + increment);
197:                        }
198:                    } else if (keyClass.getName().equals("java.lang.Long")) {
199:                        if (((Number) value).longValue() < ((Number) hiValues
200:                                .get(sequenceNameColumn)).longValue() - 1) {
201:                            value = new Long(((Number) value).longValue() + 1);
202:                            lowValues.put(sequenceNameColumn, value);
203:                        } else {
204:                            value = getSeed(sequence);
205:                            lowValues.put(sequenceNameColumn, value);
206:                            hiValues.put(sequenceNameColumn, ((Number) value)
207:                                    .longValue()
208:                                    + increment);
209:                        }
210:                    } else if (keyClass.getName()
211:                            .equals("java.math.BigInteger")) {
212:                        if (new BigInteger(value.toString())
213:                                .compareTo(new BigInteger(hiValues.get(
214:                                        sequenceNameColumn).toString())) == -1) {
215:                            value = new BigInteger(value.toString())
216:                                    .add(BigInteger.ONE);
217:                            lowValues.put(sequenceNameColumn, value);
218:                        } else {
219:                            value = getSeed(sequence);
220:                            lowValues.put(sequenceNameColumn, value);
221:                            hiValues.put(sequenceNameColumn, new BigInteger(
222:                                    value.toString()).add(new BigInteger(String
223:                                    .valueOf(increment))));
224:                        }
225:                    } else if (keyClass.getName()
226:                            .equals("java.math.BigDecimal")) {
227:                        if (new BigDecimal(value.toString())
228:                                .compareTo(new BigDecimal(hiValues.get(
229:                                        sequenceNameColumn).toString())) == -1) {
230:                            value = new BigDecimal(value.toString())
231:                                    .add(BigDecimal.ONE);
232:                            lowValues.put(sequenceNameColumn, value);
233:                        } else {
234:                            value = getSeed(sequence);
235:                            lowValues.put(sequenceNameColumn, value);
236:                            hiValues.put(sequenceNameColumn, new BigDecimal(
237:                                    value.toString()).add(new BigDecimal(String
238:                                    .valueOf(increment))));
239:                        }
240:                    } else {
241:                        if (new BigDecimal(value.toString())
242:                                .compareTo(new BigDecimal(hiValues.get(
243:                                        sequenceNameColumn).toString())) == -1) {
244:                            value = new BigDecimal(value.toString())
245:                                    .add(BigDecimal.ONE);
246:                            try {
247:                                value = new BigDecimal(value.toString())
248:                                        .add(BigDecimal.ONE);
249:                                Constructor c = keyClass
250:                                        .getConstructor(String.class);
251:                                lowValues.put(sequenceNameColumn, c
252:                                        .newInstance(value.toString()));
253:                            } catch (InvocationTargetException ite) {
254:                                throw new SQLException(ite.getTargetException()
255:                                        .toString());
256:                            } catch (Exception e) {
257:                                throw new SQLException(e.toString());
258:                            }
259:                        } else {
260:                            value = getSeed(sequence);
261:                            lowValues.put(sequenceNameColumn, value);
262:                            try {
263:                                Constructor c = keyClass
264:                                        .getConstructor(String.class);
265:                                BigDecimal temp = new BigDecimal(value
266:                                        .toString()).add(new BigDecimal(String
267:                                        .valueOf(increment)));
268:                                hiValues.put(sequenceNameColumn, c
269:                                        .newInstance(temp.toString()));
270:                            } catch (InvocationTargetException ite) {
271:                                throw new SQLException(ite.getTargetException()
272:                                        .toString());
273:                            } catch (Exception e) {
274:                                throw new SQLException(e.toString());
275:                            }
276:                        }
277:                    }
278:                }
279:                return (Number) value;
280:            }
281:
282:            public synchronized Number getCurrentValue(String sequence)
283:                    throws SQLException {
284:                if (!externalSequence && this .select == null) {
285:                    throw new IllegalStateException(
286:                            "KeyGenerator not initialized");
287:                }
288:                if (!externalSequence && !sequences.contains(sequence)
289:                        && createSequenceOnDemand) { // new sequence
290:                    Collection param = new ArrayList(1);
291:                    param.add(sequence);
292:                    dbServices.execute(insert, param);
293:                    sequences.add(sequence);
294:                }
295:                Object currentValue;
296:                try {
297:                    if (externalSequence) {
298:                        if (table == null || table.trim().length() == 0) {
299:                            currentValue = dbServices.getSingleValue("SELECT "
300:                                    + idColumn);
301:                        } else {
302:                            currentValue = dbServices.getSingleValue("SELECT "
303:                                    + idColumn + " FROM " + table);
304:                        }
305:                    } else {
306:                        Collection param = new ArrayList(1);
307:                        param.add(sequence);
308:                        currentValue = dbServices.getSingleValue(select, param);
309:                    }
310:                } catch (SQLException sqle) {
311:                    throw sqle;
312:                } finally {
313:                    dbServices.release(false);
314:                }
315:                return (Number) currentValue;
316:            }
317:
318:            protected synchronized Number getSeed(String sequence)
319:                    throws SQLException {
320:                if (!externalSequence && this .select == null) {
321:                    throw new IllegalStateException(
322:                            "KeyGenerator not initialized");
323:                }
324:                Object id = null;
325:                boolean success = false;
326:                if (externalSequence) {
327:                    try {
328:                        id = dbServices.getSingleValue("SELECT " + idColumn
329:                                + " FROM " + table);
330:                        success = true;
331:                    } finally {
332:                        dbServices.release(false);
333:                    }
334:                } else {
335:                    try {
336:                        int retryCount = 0;
337:                        if (isolationLevel != -1 && !isolationLevelSet) { // set it only once
338:                            dbServices.getConnection().setTransactionIsolation(
339:                                    isolationLevel);
340:                            isolationLevelSet = true;
341:                        }
342:                        dbServices.beginTran();
343:                        while (!success && retryCount <= retryMax) {
344:                            try {
345:                                Collection param = new ArrayList(1);
346:                                param.add(sequence);
347:                                System.out
348:                                        .println("========== param: " + param);
349:                                id = dbServices.getSingleValue(select, param);
350:                                param.add(id);
351:                                dbServices.execute(update, param);
352:                                success = true;
353:                                if (keyClass.getName().equals(
354:                                        "java.lang.Integer")) {
355:                                    id = new Integer(((Number) id).intValue()
356:                                            + increment);
357:                                } else if (keyClass.getName().equals(
358:                                        "java.lang.Long")) {
359:                                    id = new Long(((Number) id).intValue()
360:                                            + increment);
361:                                } else if (keyClass.getName().equals(
362:                                        "java.math.BigInteger")) {
363:                                    id = new BigInteger(id.toString())
364:                                            .add(new BigInteger(String
365:                                                    .valueOf(increment)));
366:                                } else if (keyClass.getName().equals(
367:                                        "java.math.BigDecimal")) {
368:                                    id = new BigDecimal(id.toString())
369:                                            .add(new BigDecimal(String
370:                                                    .valueOf(increment)));
371:                                } else {
372:                                    Constructor c = keyClass
373:                                            .getConstructor(String.class);
374:                                    id = c.newInstance(String
375:                                            .valueOf(increment));
376:                                }
377:                                break;
378:                            } catch (InstantiationException ie) {
379:                                throw new SQLException(ie.toString());
380:                            } catch (IllegalAccessException iae) {
381:                                throw new SQLException(iae.toString());
382:                            } catch (InvocationTargetException ite) {
383:                                throw new SQLException(ite.getTargetException()
384:                                        .toString());
385:                            } catch (SQLException sqle) {
386:                                if ((sqle.getSQLState() != null && sqle
387:                                        .getSQLState().equals(sqlState))
388:                                        || sqle.getErrorCode() == vendorErrorCode) {
389:                                    // duplicate key: retry
390:                                } else {
391:                                    throw sqle; // some other problem
392:                                }
393:                            }
394:                            retryCount++;
395:                            try {
396:                                wait(timeout);
397:                            } catch (InterruptedException ie) {
398:                                throw new SQLException("Cannot get unique ID");
399:                            }
400:                        }
401:                    } catch (NoSuchMethodException nsme) {
402:                        throw new SQLException(nsme.getMessage()); // should not happend
403:                    } catch (SQLException sqle) {
404:                        throw sqle;
405:                    } finally {
406:                        dbServices.commitTran(); // commit no matter what
407:                        dbServices.release(false);
408:                    }
409:                }
410:                if (!success) {
411:                    throw new SQLException("Cannot get unique ID");
412:                }
413:                return (Number) id;
414:            }
415:
416:            public String getTable() {
417:                return table;
418:            }
419:
420:            public void setTable(String table) {
421:                this .table = table;
422:            }
423:
424:            public String getIdColumn() {
425:                return idColumn;
426:            }
427:
428:            public void setIdColumn(String idColumn) {
429:                this .idColumn = idColumn;
430:            }
431:
432:            public int getIncrement() {
433:                return increment;
434:            }
435:
436:            public void setIncrement(int increment) {
437:                this .increment = increment;
438:            }
439:
440:            public DBServices getDBServices() {
441:                return dbServices;
442:            }
443:
444:            public void setDBServices(DBServices dbServices) {
445:                this .dbServices = dbServices;
446:                this .dbServices.setCacheStatements(cacheStatements);
447:            }
448:
449:            public int getRetryMax() {
450:                return retryMax;
451:            }
452:
453:            public void setRetryMax(int retryMax) {
454:                this .retryMax = retryMax;
455:            }
456:
457:            public String getSqlState() {
458:                return sqlState;
459:            }
460:
461:            public void setSqlState(String sqlState) {
462:                this .sqlState = sqlState;
463:            }
464:
465:            public long getTimeout() {
466:                return timeout;
467:            }
468:
469:            public void setTimeout(long timeout) {
470:                if (timeout < 0) {
471:                    throw new IllegalArgumentException(
472:                            "Timeout must be greater than zero");
473:                }
474:                this .timeout = timeout;
475:            }
476:
477:            public int getIsolationLevel() {
478:                return isolationLevel;
479:            }
480:
481:            public void setIsolationLevel(int isolationLevel) {
482:                this .isolationLevel = isolationLevel;
483:            }
484:
485:            public String getSequenceNameColumn() {
486:                return sequenceNameColumn;
487:            }
488:
489:            public void setSequenceNameColumn(String sequenceNameColumn) {
490:                this .sequenceNameColumn = sequenceNameColumn;
491:            }
492:
493:            public Class getKeyClass() {
494:                return keyClass;
495:            }
496:
497:            public void setKeyClass(Class keyClass) {
498:                if (Number.class.isAssignableFrom(keyClass)) {
499:                    this .keyClass = keyClass;
500:                } else {
501:                    throw new IllegalArgumentException(
502:                            "KeyClass must extend java.lang.Number");
503:                }
504:                try {
505:                    Constructor c = keyClass.getConstructor(String.class);
506:                    Object obj = c.newInstance("0");
507:                    String stringValue = obj.toString();
508:                    if (stringValue == null
509:                            && !(stringValue.equals("0") && !(stringValue
510:                                    .startsWith("0.")))) {
511:                        throw new IllegalArgumentException(
512:                                keyClass.getName()
513:                                        + ".toString() must return String value of Number");
514:                    }
515:                } catch (InvocationTargetException ite) {
516:                    throw new IllegalArgumentException(ite.getTargetException()
517:                            .toString());
518:                } catch (Exception e) {
519:                    throw new IllegalArgumentException(e.toString());
520:                }
521:            }
522:
523:            public boolean isExternalSequence() {
524:                return externalSequence;
525:            }
526:
527:            public void setExternalSequence(boolean externalSequence) {
528:                this .externalSequence = externalSequence;
529:            }
530:
531:            public Number getInitialValue() {
532:                return initialValue;
533:            }
534:
535:            public void setInitialValue(Number initialValue) {
536:                this .initialValue = initialValue;
537:            }
538:
539:            public boolean isCacheStatements() {
540:                return cacheStatements;
541:            }
542:
543:            public void setCacheStatements(boolean cacheStatements) {
544:                this .cacheStatements = cacheStatements;
545:            }
546:
547:            public boolean isCreateSequenceOnDemand() {
548:                return createSequenceOnDemand;
549:            }
550:
551:            public void setCreateSequenceOnDemand(boolean createSequenceOnDemand) {
552:                this .createSequenceOnDemand = createSequenceOnDemand;
553:            }
554:
555:            public void reset() throws SQLException {
556:                table = null;
557:                idColumn = null;
558:                sequenceNameColumn = null;
559:                increment = 10;
560:                retryMax = 3;
561:                timeout = 250;
562:                vendorErrorCode = Integer.MIN_VALUE;
563:                isolationLevel = -1;
564:                isolationLevelSet = false;
565:                lowValues.clear();
566:                hiValues.clear();
567:                keyClass = Integer.class;
568:                externalSequence = false;
569:                select = null;
570:                update = null;
571:                ;
572:                insert = null;
573:                initialValue = new Integer(0);
574:                cacheStatements = false;
575:                sequences.clear();
576:                dbServices.release(true);
577:            }
578:
579:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.