Source Code Cross Referenced for TableJDBCSeq.java in  » Database-ORM » openjpa » org » apache » openjpa » jdbc » kernel » 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 » openjpa » org.apache.openjpa.jdbc.kernel 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one
003:         * or more contributor license agreements.  See the NOTICE file
004:         * distributed with this work for additional information
005:         * regarding copyright ownership.  The ASF licenses this file
006:         * to you under the Apache License, Version 2.0 (the
007:         * "License"); you may not use this file except in compliance
008:         * with the License.  You may obtain a copy of the License at
009:         *
010:         * http://www.apache.org/licenses/LICENSE-2.0
011:         *
012:         * Unless required by applicable law or agreed to in writing,
013:         * software distributed under the License is distributed on an
014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015:         * KIND, either express or implied.  See the License for the
016:         * specific language governing permissions and limitations
017:         * under the License.    
018:         */
019:        package org.apache.openjpa.jdbc.kernel;
020:
021:        import java.io.Serializable;
022:        import java.sql.Connection;
023:        import java.sql.PreparedStatement;
024:        import java.sql.ResultSet;
025:        import java.sql.SQLException;
026:        import java.sql.Types;
027:        import java.util.HashMap;
028:
029:        import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
030:        import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
031:        import org.apache.openjpa.jdbc.meta.ClassMapping;
032:        import org.apache.openjpa.jdbc.schema.Column;
033:        import org.apache.openjpa.jdbc.schema.PrimaryKey;
034:        import org.apache.openjpa.jdbc.schema.Schema;
035:        import org.apache.openjpa.jdbc.schema.SchemaGroup;
036:        import org.apache.openjpa.jdbc.schema.SchemaTool;
037:        import org.apache.openjpa.jdbc.schema.Schemas;
038:        import org.apache.openjpa.jdbc.schema.Table;
039:        import org.apache.openjpa.jdbc.sql.DBDictionary;
040:        import org.apache.openjpa.jdbc.sql.RowImpl;
041:        import org.apache.openjpa.jdbc.sql.SQLBuffer;
042:        import org.apache.openjpa.jdbc.sql.SQLExceptions;
043:        import org.apache.openjpa.lib.conf.Configurable;
044:        import org.apache.openjpa.lib.conf.Configuration;
045:        import org.apache.openjpa.lib.conf.Configurations;
046:        import org.apache.openjpa.lib.log.Log;
047:        import org.apache.openjpa.lib.util.Localizer;
048:        import org.apache.openjpa.lib.util.Options;
049:        import org.apache.openjpa.meta.JavaTypes;
050:        import org.apache.openjpa.util.InvalidStateException;
051:        import serp.util.Numbers;
052:        import serp.util.Strings;
053:
054:        ////////////////////////////////////////////////////////////
055:        // NOTE: Do not change property names; see SequenceMetaData
056:        // and SequenceMapping for standard property names.
057:        ////////////////////////////////////////////////////////////
058:
059:        /**
060:         * {@link JDBCSeq} implementation that uses a database table
061:         * for sequence number generation. This base implementation uses a single
062:         * row for a global sequence number.
063:         *
064:         * @author Abe White
065:         */
066:        public class TableJDBCSeq extends AbstractJDBCSeq implements 
067:                Configurable {
068:
069:            public static final String ACTION_DROP = "drop";
070:            public static final String ACTION_ADD = "add";
071:            public static final String ACTION_GET = "get";
072:            public static final String ACTION_SET = "set";
073:
074:            private static final Localizer _loc = Localizer
075:                    .forPackage(TableJDBCSeq.class);
076:
077:            private transient JDBCConfiguration _conf = null;
078:            private transient Log _log = null;
079:            private int _alloc = 50;
080:            private int _intValue = 1;
081:            private final HashMap _stat = new HashMap();
082:
083:            private String _table = "OPENJPA_SEQUENCE_TABLE";
084:            private String _seqColumnName = "SEQUENCE_VALUE";
085:            private String _pkColumnName = "ID";
086:
087:            private Column _seqColumn = null;
088:            private Column _pkColumn = null;
089:            private int _schemasIdx = 0;
090:
091:            /**
092:             * The sequence table name. Defaults to <code>OPENJPA_SEQUENCE_TABLE</code>.
093:             * By default, the table will be placed in the first schema listed in your
094:             * <code>openjpa.jdbc.Schemas</code> property, or in the default schema if
095:             * the property is not given. If you specify a table name in the form
096:             * <code>&lt;schema&gt;.&lt;table&gt;</code>, then the given schema
097:             * will be used.
098:             */
099:            public String getTable() {
100:                return _table;
101:            }
102:
103:            /**
104:             * The sequence table name. Defaults to <code>OPENJPA_SEQUENCE_TABLE</code>.
105:             * By default, the table will be placed in the first schema listed in your
106:             * <code>openjpa.jdbc.Schemas</code> property, or in the default schema if
107:             * the property is not given. If you specify a table name in the form
108:             * <code>&lt;schema&gt;.&lt;table&gt;</code>, then the given schema
109:             * will be used.
110:             */
111:            public void setTable(String name) {
112:                _table = name;
113:            }
114:
115:            /**
116:             * @deprecated Use {@link #setTable}. Retained for
117:             * backwards-compatibility	with auto-configuration.
118:             */
119:            public void setTableName(String name) {
120:                setTable(name);
121:            }
122:
123:            /**
124:             * The name of the column that holds the sequence value. Defaults
125:             * to <code>SEQUENCE_VALUE</code>.
126:             */
127:            public String getSequenceColumn() {
128:                return _seqColumnName;
129:            }
130:
131:            /**
132:             * The name of the column that holds the sequence value. Defaults
133:             * to <code>SEQUENCE_VALUE</code>.
134:             */
135:            public void setSequenceColumn(String sequenceColumn) {
136:                _seqColumnName = sequenceColumn;
137:            }
138:
139:            /**
140:             * The name of the table's primary key column. Defaults to
141:             * <code>ID</code>.
142:             */
143:            public String getPrimaryKeyColumn() {
144:                return _pkColumnName;
145:            }
146:
147:            /**
148:             * The name of the table's primary key column. Defaults to
149:             * <code>ID</code>.
150:             */
151:            public void setPrimaryKeyColumn(String primaryKeyColumn) {
152:                _pkColumnName = primaryKeyColumn;
153:            }
154:
155:            /**
156:             * Return the number of sequences to allocate for each update of the
157:             * sequence table. Sequence numbers will be grabbed in blocks of this
158:             * value to reduce the number of transactions that must be performed on
159:             * the sequence table.
160:             */
161:            public int getAllocate() {
162:                return _alloc;
163:            }
164:
165:            /**
166:             * Return the number of sequences to allocate for each update of the
167:             * sequence table. Sequence numbers will be grabbed in blocks of this
168:             * value to reduce the number of transactions that must be performed on
169:             * the sequence table.
170:             */
171:            public void setAllocate(int alloc) {
172:                _alloc = alloc;
173:            }
174:
175:            /**
176:             * Return the number as the initial number for the 
177:             * GeneratedValue.TABLE strategy to start with. 
178:             * @return an initial number
179:             */
180:            public int getInitialValue() {
181:                return _intValue;
182:            }
183:
184:            /**
185:             * Set the initial number in the table for the GeneratedValue.TABLE
186:             * strategy to use as initial number. 
187:             * @param intValue. The initial number
188:             */
189:            public void setInitialValue(int intValue) {
190:                _intValue = intValue;
191:            }
192:
193:            /**
194:             * @deprecated Use {@link #setAllocate}. Retained for backwards
195:             * compatibility of auto-configuration.
196:             */
197:            public void setIncrement(int inc) {
198:                setAllocate(inc);
199:            }
200:
201:            public JDBCConfiguration getConfiguration() {
202:                return _conf;
203:            }
204:
205:            public void setConfiguration(Configuration conf) {
206:                _conf = (JDBCConfiguration) conf;
207:                _log = _conf.getLog(JDBCConfiguration.LOG_RUNTIME);
208:            }
209:
210:            public void startConfiguration() {
211:            }
212:
213:            public void endConfiguration() {
214:                buildTable();
215:            }
216:
217:            public void addSchema(ClassMapping mapping, SchemaGroup group) {
218:                // Since the table is created by openjpa internally
219:                // we can create the table for each schema within the PU
220:                // in here.
221:
222:                Schema[] schemas = group.getSchemas();
223:                for (int i = 0; i < schemas.length; i++) {
224:                    String schemaName = Strings.getPackageName(_table);
225:                    if (schemaName.length() == 0)
226:                        schemaName = Schemas.getNewTableSchema(_conf);
227:                    if (schemaName == null)
228:                        schemaName = schemas[i].getName();
229:
230:                    // create table in this group
231:                    Schema schema = group.getSchema(schemaName);
232:                    if (schema == null)
233:                        schema = group.addSchema(schemaName);
234:
235:                    schema.importTable(_pkColumn.getTable());
236:                    // we need to reset the table name in the column with the
237:                    // fully qualified name for matching the table name from the
238:                    // Column.
239:                    _pkColumn.resetTableName(schemaName + "."
240:                            + _pkColumn.getTableName());
241:                    // some databases require to create an index for the sequence table
242:                    _conf.getDBDictionaryInstance().createIndexIfNecessary(
243:                            schema, _table, _pkColumn);
244:
245:                }
246:            }
247:
248:            protected Object nextInternal(JDBCStore store, ClassMapping mapping)
249:                    throws Exception {
250:                // if needed, grab the next handful of ids
251:                Status stat = getStatus(mapping);
252:                if (stat == null)
253:                    throw new InvalidStateException(_loc.get("bad-seq-type",
254:                            getClass(), mapping));
255:
256:                while (true) {
257:                    synchronized (stat) {
258:                        // make sure seq is at least 1, since autoassigned ids of 0 can
259:                        // conflict with uninitialized values
260:                        stat.seq = Math.max(stat.seq, 1);
261:                        if (stat.seq < stat.max)
262:                            return Numbers.valueOf(stat.seq++);
263:                    }
264:                    allocateSequence(store, mapping, stat, _alloc, true);
265:                }
266:            }
267:
268:            protected Object currentInternal(JDBCStore store,
269:                    ClassMapping mapping) throws Exception {
270:                if (current == null) {
271:                    Connection conn = getConnection(store);
272:                    try {
273:                        long cur = getSequence(mapping, conn);
274:                        if (cur != -1)
275:                            current = Numbers.valueOf(cur);
276:                    } finally {
277:                        closeConnection(conn);
278:                    }
279:                }
280:                return super .currentInternal(store, mapping);
281:            }
282:
283:            protected void allocateInternal(int count, JDBCStore store,
284:                    ClassMapping mapping) throws SQLException {
285:                Status stat = getStatus(mapping);
286:                if (stat == null)
287:                    return;
288:
289:                while (true) {
290:                    int available;
291:                    synchronized (stat) {
292:                        available = (int) (stat.max - stat.seq);
293:                        if (available >= count)
294:                            return;
295:                    }
296:                    allocateSequence(store, mapping, stat, count - available,
297:                            false);
298:                }
299:            }
300:
301:            /**
302:             * Return the appropriate status object for the given class, or null
303:             * if cannot handle the given class. The mapping may be null.
304:             */
305:            protected Status getStatus(ClassMapping mapping) {
306:                Status status = (Status) _stat.get(mapping);
307:                if (status == null) {
308:                    status = new Status();
309:                    _stat.put(mapping, status);
310:                }
311:                return status;
312:
313:            }
314:
315:            /**
316:             * Add the primary key column to the given table and return it.
317:             */
318:            protected Column addPrimaryKeyColumn(Table table) {
319:                DBDictionary dict = _conf.getDBDictionaryInstance();
320:                Column pkColumn = table.addColumn(dict.getValidColumnName(
321:                        getPrimaryKeyColumn(), table));
322:                pkColumn.setType(dict.getPreferredType(Types.TINYINT));
323:                pkColumn.setJavaType(JavaTypes.INT);
324:                return pkColumn;
325:            }
326:
327:            /**
328:             * Return the primary key value for the given class.
329:             */
330:            protected Object getPrimaryKey(ClassMapping mapping) {
331:                return Numbers.valueOf(0);
332:            }
333:
334:            /**
335:             * Creates the object-level representation of the sequence table.
336:             */
337:            private void buildTable() {
338:                String tableName = Strings.getClassName(_table);
339:                String schemaName = Strings.getPackageName(_table);
340:                if (schemaName.length() == 0)
341:                    schemaName = Schemas.getNewTableSchema(_conf);
342:
343:                SchemaGroup group = new SchemaGroup();
344:                Schema schema = group.addSchema(schemaName);
345:
346:                Table table = schema.addTable(tableName);
347:                _pkColumn = addPrimaryKeyColumn(table);
348:                PrimaryKey pk = table.addPrimaryKey();
349:                pk.addColumn(_pkColumn);
350:
351:                DBDictionary dict = _conf.getDBDictionaryInstance();
352:                _seqColumn = table.addColumn(dict.getValidColumnName(
353:                        _seqColumnName, table));
354:                _seqColumn.setType(dict.getPreferredType(Types.BIGINT));
355:                _seqColumn.setJavaType(JavaTypes.LONG);
356:            }
357:
358:            /**
359:             * Updates the max available sequence value.
360:             */
361:            private void allocateSequence(JDBCStore store,
362:                    ClassMapping mapping, Status stat, int alloc,
363:                    boolean updateStatSeq) throws SQLException {
364:                Connection conn = getConnection(store);
365:                try {
366:                    if (setSequence(mapping, stat, alloc, updateStatSeq, conn))
367:                        return;
368:                } catch (SQLException se) {
369:                    throw SQLExceptions.getStore(
370:                            _loc.get("bad-seq-up", _table), se, _conf
371:                                    .getDBDictionaryInstance());
372:                } finally {
373:                    closeConnection(conn);
374:                }
375:
376:                try {
377:                    // possible that we might get errors when inserting if
378:                    // another thread/process is inserting same pk at same time
379:                    SQLException err = null;
380:                    // ### why does this not call getConnection() / closeConnection()?
381:                    conn = _conf.getDataSource2(store.getContext())
382:                            .getConnection();
383:                    try {
384:                        insertSequence(mapping, conn);
385:                    } catch (SQLException se) {
386:                        err = se;
387:                    } finally {
388:                        try {
389:                            conn.close();
390:                        } catch (SQLException se) {
391:                        }
392:                    }
393:
394:                    // now we should be able to update...
395:                    conn = getConnection(store);
396:                    try {
397:                        if (!setSequence(mapping, stat, alloc, updateStatSeq,
398:                                conn))
399:                            throw (err != null) ? err : new SQLException(_loc
400:                                    .get("no-seq-row", mapping, _table)
401:                                    .getMessage());
402:                    } finally {
403:                        closeConnection(conn);
404:                    }
405:                } catch (SQLException se2) {
406:                    throw SQLExceptions.getStore(
407:                            _loc.get("bad-seq-up", _table), se2, _conf
408:                                    .getDBDictionaryInstance());
409:                }
410:            }
411:
412:            /**
413:             * Inserts the initial sequence information into the database, if any.
414:             */
415:            private void insertSequence(ClassMapping mapping, Connection conn)
416:                    throws SQLException {
417:                if (_log.isTraceEnabled())
418:                    _log.trace(_loc.get("insert-seq"));
419:
420:                Object pk = getPrimaryKey(mapping);
421:                if (pk == null)
422:                    throw new InvalidStateException(_loc.get("bad-seq-type",
423:                            getClass(), mapping));
424:
425:                DBDictionary dict = _conf.getDBDictionaryInstance();
426:                String tableName = resolveTableName(mapping, _pkColumn
427:                        .getTable());
428:                SQLBuffer insert = new SQLBuffer(dict).append("INSERT INTO ")
429:                        .append(tableName).append(" (").append(_pkColumn)
430:                        .append(", ").append(_seqColumn).append(") VALUES (")
431:                        .appendValue(pk, _pkColumn).append(", ").appendValue(
432:                                _intValue, _seqColumn).append(")");
433:
434:                boolean wasAuto = conn.getAutoCommit();
435:                if (!wasAuto && !suspendInJTA())
436:                    conn.setAutoCommit(true);
437:
438:                PreparedStatement stmnt = null;
439:                try {
440:                    stmnt = prepareStatement(conn, insert);
441:                    executeUpdate(_conf, conn, stmnt, insert,
442:                            RowImpl.ACTION_INSERT);
443:                } finally {
444:                    if (stmnt != null)
445:                        try {
446:                            stmnt.close();
447:                        } catch (SQLException se) {
448:                        }
449:                    if (!wasAuto && !suspendInJTA())
450:                        conn.setAutoCommit(false);
451:                }
452:            }
453:
454:            /**
455:             * Return the current sequence value, or -1 if unattainable.
456:             */
457:            protected long getSequence(ClassMapping mapping, Connection conn)
458:                    throws SQLException {
459:                if (_log.isTraceEnabled())
460:                    _log.trace(_loc.get("get-seq"));
461:
462:                Object pk = getPrimaryKey(mapping);
463:                if (pk == null)
464:                    return -1;
465:
466:                DBDictionary dict = _conf.getDBDictionaryInstance();
467:                SQLBuffer sel = new SQLBuffer(dict).append(_seqColumn);
468:                SQLBuffer where = new SQLBuffer(dict).append(_pkColumn).append(
469:                        " = ").appendValue(pk, _pkColumn);
470:                String tableName = resolveTableName(mapping, _seqColumn
471:                        .getTable());
472:                SQLBuffer tables = new SQLBuffer(dict).append(tableName);
473:
474:                SQLBuffer select = dict.toSelect(sel, null, tables, where,
475:                        null, null, null, false, dict.supportsSelectForUpdate,
476:                        0, Long.MAX_VALUE, false, true);
477:
478:                PreparedStatement stmnt = prepareStatement(conn, select);
479:                ResultSet rs = null;
480:                try {
481:                    rs = executeQuery(_conf, conn, stmnt, select);
482:                    return getSequence(rs, dict);
483:                } finally {
484:                    if (rs != null)
485:                        try {
486:                            rs.close();
487:                        } catch (SQLException se) {
488:                        }
489:                    if (stmnt != null)
490:                        try {
491:                            stmnt.close();
492:                        } catch (SQLException se) {
493:                        }
494:                }
495:            }
496:
497:            /**
498:             * Grabs the next handful of sequence numbers.
499:             *
500:             * @return true if the sequence was updated, false if no sequence
501:             * row existed for this mapping
502:             */
503:            protected boolean setSequence(ClassMapping mapping, Status stat,
504:                    int inc, boolean updateStatSeq, Connection conn)
505:                    throws SQLException {
506:                if (_log.isTraceEnabled())
507:                    _log.trace(_loc.get("update-seq"));
508:
509:                Object pk = getPrimaryKey(mapping);
510:                if (pk == null)
511:                    throw new InvalidStateException(_loc.get("bad-seq-type",
512:                            getClass(), mapping));
513:
514:                DBDictionary dict = _conf.getDBDictionaryInstance();
515:                SQLBuffer where = new SQLBuffer(dict).append(_pkColumn).append(
516:                        " = ").appendValue(pk, _pkColumn);
517:
518:                // loop until we have a successful atomic select/update sequence
519:                long cur = 0;
520:                PreparedStatement stmnt;
521:                ResultSet rs;
522:                SQLBuffer upd;
523:                for (int updates = 0; updates == 0;) {
524:                    stmnt = null;
525:                    rs = null;
526:                    try {
527:                        cur = getSequence(mapping, conn);
528:                        if (cur == -1)
529:                            return false;
530:
531:                        // update the value
532:                        upd = new SQLBuffer(dict);
533:                        String tableName = resolveTableName(mapping, _seqColumn
534:                                .getTable());
535:                        upd.append("UPDATE ").append(tableName).append(" SET ")
536:                                .append(_seqColumn).append(" = ").appendValue(
537:                                        Numbers.valueOf(cur + inc), _seqColumn)
538:                                .append(" WHERE ").append(where)
539:                                .append(" AND ").append(_seqColumn).append(
540:                                        " = ").appendValue(
541:                                        Numbers.valueOf(cur), _seqColumn);
542:
543:                        stmnt = prepareStatement(conn, upd);
544:                        updates = executeUpdate(_conf, conn, stmnt, upd,
545:                                RowImpl.ACTION_UPDATE);
546:                    } finally {
547:                        if (rs != null)
548:                            try {
549:                                rs.close();
550:                            } catch (SQLException se) {
551:                            }
552:                        if (stmnt != null)
553:                            try {
554:                                stmnt.close();
555:                            } catch (SQLException se) {
556:                            }
557:                    }
558:                }
559:
560:                // setup new sequence range        
561:                synchronized (stat) {
562:                    if (updateStatSeq && stat.seq < cur)
563:                        stat.seq = cur;
564:                    if (stat.max < cur + inc)
565:                        stat.max = cur + inc;
566:                }
567:                return true;
568:            }
569:
570:            /**
571:             * Resolve a fully qualified table name
572:             * 
573:             * @param class
574:             *            mapping to get the schema name
575:             */
576:            public String resolveTableName(ClassMapping mapping, Table table) {
577:                String sName = mapping.getTable().getSchemaName();
578:                String tableName;
579:                if (sName == null)
580:                    tableName = table.getFullName();
581:                else
582:                    tableName = sName + "." + table.getName();
583:                return tableName;
584:            }
585:
586:            /**
587:             * Creates the sequence table in the DB.
588:             */
589:            public void refreshTable() throws SQLException {
590:                if (_log.isInfoEnabled())
591:                    _log.info(_loc.get("make-seq-table"));
592:
593:                // create the table
594:                SchemaTool tool = new SchemaTool(_conf);
595:                tool.setIgnoreErrors(true);
596:                tool.createTable(_pkColumn.getTable());
597:            }
598:
599:            /**
600:             * Drops the sequence table in the DB.
601:             */
602:            public void dropTable() throws SQLException {
603:                if (_log.isInfoEnabled())
604:                    _log.info(_loc.get("drop-seq-table"));
605:
606:                // drop the table
607:                SchemaTool tool = new SchemaTool(_conf);
608:                tool.setIgnoreErrors(true);
609:                tool.dropTable(_pkColumn.getTable());
610:            }
611:
612:            /////////
613:            // Main
614:            /////////
615:
616:            /**
617:             * Usage: java org.apache.openjpa.jdbc.schema.TableJDBCSequence [option]*
618:             * -action/-a &lt;add | drop | get | set&gt; [value]
619:             *  Where the following options are recognized.
620:             * <ul>
621:             * <li><i>-properties/-p &lt;properties file or resource&gt;</i>: The
622:             * path or resource name of a OpenJPA properties file containing
623:             * information such as the license key	and connection data as
624:             * outlined in {@link JDBCConfiguration}. Optional.</li>
625:             * <li><i>-&lt;property name&gt; &lt;property value&gt;</i>: All bean
626:             * properties of the OpenJPA {@link JDBCConfiguration} can be set by
627:             * using their	names and supplying a value. For example:
628:             * <code>-licenseKey adslfja83r3lkadf</code></li>
629:             * </ul>
630:             *  The various actions are as follows.
631:             * <ul>
632:             * <li><i>add</i>: Create the sequence table.</li>
633:             * <li><i>drop</i>: Drop the sequence table.</li>
634:             * <li><i>get</i>: Print the current sequence value.</li>
635:             * <li><i>set</i>: Set the sequence value.</li>
636:             * </ul>
637:             */
638:            public static void main(String[] args) throws Exception {
639:                Options opts = new Options();
640:                final String[] arguments = opts.setFromCmdLine(args);
641:                boolean ret = Configurations.runAgainstAllAnchors(opts,
642:                        new Configurations.Runnable() {
643:                            public boolean run(Options opts) throws Exception {
644:                                JDBCConfiguration conf = new JDBCConfigurationImpl();
645:                                try {
646:                                    return TableJDBCSeq.run(conf, arguments,
647:                                            opts);
648:                                } finally {
649:                                    conf.close();
650:                                }
651:                            }
652:                        });
653:                if (!ret)
654:                    System.out.println(_loc.get("seq-usage"));
655:            }
656:
657:            /**
658:             * Run the tool. Returns false if invalid options were given.
659:             */
660:            public static boolean run(JDBCConfiguration conf, String[] args,
661:                    Options opts) throws Exception {
662:                String action = opts.removeProperty("action", "a", null);
663:                Configurations.populateConfiguration(conf, opts);
664:                return run(conf, args, action);
665:            }
666:
667:            /**
668:             * Run the tool. Return false if an invalid option was given.
669:             */
670:            public static boolean run(JDBCConfiguration conf, String[] args,
671:                    String action) throws Exception {
672:                if (args.length > 1
673:                        || (args.length != 0 && !ACTION_SET.equals(action)))
674:                    return false;
675:
676:                TableJDBCSeq seq = new TableJDBCSeq();
677:                String props = Configurations.getProperties(conf.getSequence());
678:                Configurations.configureInstance(seq, conf, props);
679:
680:                if (ACTION_DROP.equals(action))
681:                    seq.dropTable();
682:                else if (ACTION_ADD.equals(action))
683:                    seq.refreshTable();
684:                else if (ACTION_GET.equals(action) || ACTION_SET.equals(action)) {
685:                    Connection conn = conf.getDataSource2(null).getConnection();
686:                    try {
687:                        long cur = seq.getSequence(null, conn);
688:                        if (ACTION_GET.equals(action))
689:                            System.out.println(cur);
690:                        else {
691:                            long set;
692:                            if (args.length > 0)
693:                                set = Long.parseLong(args[0]);
694:                            else
695:                                set = cur + seq.getAllocate();
696:                            if (set < cur)
697:                                set = cur;
698:                            else {
699:                                Status stat = seq.getStatus(null);
700:                                seq.setSequence(null, stat, (int) (set - cur),
701:                                        true, conn);
702:                                set = stat.seq;
703:                            }
704:                            System.err.println(set);
705:                        }
706:                    } catch (NumberFormatException nfe) {
707:                        return false;
708:                    } finally {
709:                        try {
710:                            conn.close();
711:                        } catch (SQLException se) {
712:                        }
713:                    }
714:                } else
715:                    return false;
716:                return true;
717:            }
718:
719:            /**
720:             * Helper struct to hold status information.
721:             */
722:            protected static class Status implements  Serializable {
723:
724:                public long seq = 1L;
725:                public long max = 0L;
726:            }
727:
728:            /**
729:             * This method is to provide override for non-JDBC or JDBC-like 
730:             * implementation of preparing statement.
731:             */
732:            protected PreparedStatement prepareStatement(Connection conn,
733:                    SQLBuffer buf) throws SQLException {
734:                return buf.prepareStatement(conn);
735:            }
736:
737:            /**
738:             * This method is to provide override for non-JDBC or JDBC-like 
739:             * implementation of executing update.
740:             */
741:            protected int executeUpdate(JDBCConfiguration conf,
742:                    Connection conn, PreparedStatement stmnt, SQLBuffer buf,
743:                    int opcode) throws SQLException {
744:                return stmnt.executeUpdate();
745:            }
746:
747:            /**
748:             * This method is to provide override for non-JDBC or JDBC-like 
749:             * implementation of executing query.
750:             */
751:            protected ResultSet executeQuery(JDBCConfiguration conf,
752:                    Connection conn, PreparedStatement stmnt, SQLBuffer buf)
753:                    throws SQLException {
754:                return stmnt.executeQuery();
755:            }
756:
757:            /**
758:             * This method is to provide override for non-JDBC or JDBC-like 
759:             * implementation of getting sequence from the result set.
760:             */
761:            protected long getSequence(ResultSet rs, DBDictionary dict)
762:                    throws SQLException {
763:                if (rs == null || !rs.next())
764:                    return -1;
765:                return dict.getLong(rs, 1);
766:            }
767:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.