Source Code Cross Referenced for HighLowJdbcKeyGenerator.java in  » Testing » PolePosition-0.20 » com » versant » core » jdbc » sql » 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 » Testing » PolePosition 0.20 » com.versant.core.jdbc.sql 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 1998 - 2005 Versant Corporation
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         * Versant Corporation - initial API and implementation
010:         */
011:        package com.versant.core.jdbc.sql;
012:
013:        import com.versant.core.metadata.MDStatics;
014:        import com.versant.core.jdbc.JdbcKeyGenerator;
015:        import com.versant.core.jdbc.JdbcKeyGeneratorFactory;
016:        import com.versant.core.jdbc.JdbcMetaDataBuilder;
017:        import com.versant.core.jdbc.metadata.JdbcColumn;
018:        import com.versant.core.jdbc.metadata.JdbcTable;
019:        import com.versant.core.jdbc.metadata.JdbcMappingResolver;
020:
021:        import java.sql.*;
022:        import java.util.HashSet;
023:        import java.util.Iterator;
024:
025:        import com.versant.core.common.BindingSupportImpl;
026:
027:        /**
028:         * This key generator uses a last used id table and a grab size to generate
029:         * primary keys. Each instance generates keys for a single class.
030:         */
031:        public class HighLowJdbcKeyGenerator implements  JdbcKeyGenerator {
032:
033:            /**
034:             * Our args bean.
035:             */
036:            public static class Args {
037:
038:                private String tableName = "jdo_keygen";
039:
040:                private String keyColumnName = "table_name";
041:                private String valueColumnName = "last_used_id";
042:                private int keyColumnLength = 64;
043:                private int grabSize = 10;
044:                private int start;
045:                private boolean createTable = true;
046:                private String pkConstraint;
047:
048:                public Args() {
049:                }
050:
051:                public String getTableName() {
052:                    return tableName;
053:                }
054:
055:                public void setTableName(String tableName) {
056:                    this .tableName = tableName;
057:                }
058:
059:                public String getKeyColumnName() {
060:                    return keyColumnName;
061:                }
062:
063:                public void setKeyColumnName(String keyColumnName) {
064:                    this .keyColumnName = keyColumnName;
065:                }
066:
067:                public String getValueColumnName() {
068:                    return valueColumnName;
069:                }
070:
071:                public void setValueColumnName(String valueColumnName) {
072:                    this .valueColumnName = valueColumnName;
073:                }
074:
075:                public int getKeyColumnLength() {
076:                    return keyColumnLength;
077:                }
078:
079:                public void setKeyColumnLength(int keyColumnLength) {
080:                    this .keyColumnLength = keyColumnLength;
081:                }
082:
083:                public int getGrabSize() {
084:                    return grabSize;
085:                }
086:
087:                public void setGrabSize(int grabSize) {
088:                    this .grabSize = grabSize;
089:                }
090:
091:                public int getStart() {
092:                    return start;
093:                }
094:
095:                public void setStart(int start) {
096:                    this .start = start;
097:                }
098:
099:                public boolean isCreateTable() {
100:                    return createTable;
101:                }
102:
103:                public void setCreateTable(boolean createTable) {
104:                    this .createTable = createTable;
105:                }
106:
107:                public String getPkConstraint() {
108:                    return pkConstraint;
109:                }
110:
111:                public void setPkConstraint(String pkConstraint) {
112:                    this .pkConstraint = pkConstraint;
113:                }
114:            }
115:
116:            /**
117:             * Our factory.
118:             */
119:            public static class Factory implements  JdbcKeyGeneratorFactory {
120:
121:                /**
122:                 * Create a javabean to hold args for a createJdbcKeyGenerator call or null
123:                 * if the key generator does not accept any arguments.
124:                 */
125:                public Object createArgsBean() {
126:                    return new Args();
127:                }
128:
129:                /**
130:                 * Create a JdbcKeyGenerator for class using props as parameters. The
131:                 * instance returned may be new or may be a shared instance.
132:                 */
133:                public JdbcKeyGenerator createJdbcKeyGenerator(
134:                        String className, JdbcTable classTable, Object args) {
135:                    HighLowJdbcKeyGenerator kg = new HighLowJdbcKeyGenerator(
136:                            classTable, (Args) args);
137:                    return kg;
138:                }
139:            }
140:
141:            protected JdbcTable classTable;
142:            protected JdbcColumn classPk;
143:            protected int pkJavaTypeCode;
144:
145:            protected String tableName;
146:            protected String keyColumnName;
147:            protected String valueColumnName;
148:            protected int keyColumnLength;
149:            protected int grabSize;
150:            protected int start;
151:            protected boolean createTable;
152:            protected String pkConstraint;
153:
154:            protected String updateSql;
155:            protected String selectSql;
156:            protected int lastUsed;
157:            protected int grabLeft;
158:
159:            public HighLowJdbcKeyGenerator(JdbcTable classTable, Args args) {
160:                if (classTable.pk.length > 1) {
161:                    throw new IllegalArgumentException(
162:                            "Cannot use HIGH/LOW key generator on a table with multiple "
163:                                    + "primary key columns");
164:                }
165:                this .classTable = classTable;
166:                classPk = classTable.pk[0];
167:                pkJavaTypeCode = classPk.javaTypeCode;
168:                tableName = args.getTableName();
169:                keyColumnName = args.getKeyColumnName();
170:                valueColumnName = args.getValueColumnName();
171:                keyColumnLength = args.getKeyColumnLength();
172:                grabSize = args.getGrabSize();
173:                start = args.getStart();
174:                createTable = args.isCreateTable();
175:                pkConstraint = args.getPkConstraint();
176:            }
177:
178:            /**
179:             * Initialize this key generator. This is called when the JDO
180:             * implementation initializes before any keys are generated. Key
181:             * generators should use this to avoid popular race conditions and
182:             * deadlock opportunities (e.g. multiple 'select max(id) from table'
183:             * statements executing at the same time). If the same key generator
184:             * instance is used on more than one class this will be called once
185:             * for each class.
186:             *
187:             * @param className  The name of the class
188:             * @param classTable The table for the class
189:             * @param con        Connection to the DataSource for the class
190:             */
191:            public void init(String className, JdbcTable classTable,
192:                    Connection con) throws SQLException {
193:
194:                // generate our update and select statements
195:                String where = " where " + keyColumnName + " = '"
196:                        + classTable.name + "'";
197:                updateSql = "update " + tableName + " set " + valueColumnName
198:                        + " = " + valueColumnName + " + ?" + where;
199:                selectSql = "select " + valueColumnName + " from " + tableName
200:                        + where;
201:
202:                // make sure there is a row in our keygen table for our class
203:                Statement stat = null;
204:                PreparedStatement ps = null;
205:                try {
206:                    ps = con.prepareStatement(updateSql);
207:                    ps.setInt(1, 0);
208:                    if (ps.executeUpdate() == 0) {
209:                        stat = con.createStatement();
210:                        int first = start;
211:                        if (first == 0) {
212:                            String sql = "select max(" + classPk.name
213:                                    + ") from " + classTable.name;
214:                            ResultSet rs = null;
215:                            try {
216:                                rs = stat.executeQuery(sql);
217:                                rs.next();
218:                                first = rs.getInt(1);
219:                            } finally {
220:                                cleanup(rs);
221:                            }
222:                        }
223:                        String sql = "insert into " + tableName + " ("
224:                                + keyColumnName + ", " + valueColumnName
225:                                + ") values ('" + classTable.name + "', "
226:                                + first + ")";
227:                        stat.execute(sql);
228:                    }
229:                } finally {
230:                    cleanup(ps);
231:                    cleanup(stat);
232:                }
233:            }
234:
235:            /**
236:             * If the new key can only be detirmined after the new row has been
237:             * inserted (e.g. if using a database autoincrement column) then this
238:             * should return true.
239:             */
240:            public boolean isPostInsertGenerator() {
241:                return false;
242:            }
243:
244:            /**
245:             * Does this key generator require its own connection? If it does then
246:             * one will be obtained to generate the key and committed after the
247:             * key has been generated.
248:             */
249:            public boolean isRequiresOwnConnection() {
250:                return grabSize > 1 && grabLeft == 0;
251:            }
252:
253:            /**
254:             * Add any JdbcTable instances that this key generator requires to the
255:             * supplied set. This method is called once per key generator during meta
256:             * data generation. Any tables returned will be added to the meta data and
257:             * will get into SQL scripts and so on. If the same key generator
258:             * instance is returned more than once by a factory then this method
259:             * will still only be called once per instance.
260:             */
261:            public void addKeyGenTables(HashSet set, JdbcMetaDataBuilder mdb) {
262:                if (!createTable)
263:                    return;
264:
265:                // do not create a table if there is already one with our tableName
266:                for (Iterator i = set.iterator(); i.hasNext();) {
267:                    JdbcTable t = (JdbcTable) i.next();
268:                    if (t.name.equals(tableName))
269:                        return;
270:                }
271:
272:                // create the table and add it
273:                JdbcTable t = new JdbcTable();
274:                t.sqlDriver = mdb.getSqlDriver();
275:                t.name = tableName;
276:                t.comment = getClass().getName();
277:                t.pkConstraintName = pkConstraint == null ? "pk_" + tableName
278:                        : pkConstraint;
279:                JdbcMappingResolver mr = mdb.getMappingResolver();
280:                JdbcColumn keyCol = new JdbcColumn(mr
281:                        .resolveMapping(String.class), mr);
282:                keyCol.name = keyColumnName;
283:                keyCol.length = keyColumnLength;
284:                keyCol.nulls = false;
285:                JdbcColumn valueCol = new JdbcColumn(mr
286:                        .resolveMapping(Integer.TYPE), mr);
287:
288:                valueCol.name = valueColumnName;
289:                valueCol.nulls = false;
290:                t.cols = new JdbcColumn[] { keyCol, valueCol };
291:                t.setPk(new JdbcColumn[] { keyCol });
292:                set.add(t);
293:            }
294:
295:            /**
296:             * Generate a new primary key value for a new instance of the supplied
297:             * class prior to the row being inserted. The values generated will be used
298:             * to populate a new OID and then set on a PreparedStatement for the
299:             * insert. This is called if isPostInsertGenerator returns false.
300:             * <p/>
301:             * The newObjectCount parameter indicates the number of new objects that
302:             * will be inserted (including this one) in the same transaction using
303:             * this key generator. This may be used to optimize the behavior of the
304:             * key generator or be ignored. The highlow key generator uses this value
305:             * instead of its grabSize to avoid executing redundant updates and
306:             * selects.<p>
307:             *
308:             * @param className      The name of the class
309:             * @param classTable     The table for the class
310:             * @param newObjectCount The number of new objects being created
311:             * @param data           The array to store the key values in.
312:             * @param con            Connection to the DataSource for the class.
313:             * @throws SQLException on errors
314:             */
315:            public synchronized void generatePrimaryKeyPre(String className,
316:                    JdbcTable classTable, int newObjectCount, Object[] data,
317:                    Connection con) throws SQLException {
318:                int pk;
319:                if (grabSize == 1) {
320:                    pk = lookupNewNumber(con, grabSize);
321:                } else {
322:                    if (grabLeft == 0) {
323:                        int effectiveGrabSize = newObjectCount;
324:                        if (effectiveGrabSize < grabSize)
325:                            effectiveGrabSize = grabSize;
326:                        lastUsed = lookupNewNumber(con, effectiveGrabSize);
327:                        grabLeft = effectiveGrabSize - 1;
328:                    } else {
329:                        --grabLeft;
330:                    }
331:                    pk = lastUsed++;
332:                }
333:                switch (pkJavaTypeCode) {
334:                case MDStatics.INTW:
335:                case MDStatics.INT:
336:                    data[0] = new Integer((int) pk);
337:                    break;
338:                case MDStatics.SHORTW:
339:                case MDStatics.SHORT:
340:                    data[0] = new Short((short) pk);
341:                    break;
342:                case MDStatics.BYTEW:
343:                case MDStatics.BYTE:
344:                    data[0] = new Byte((byte) pk);
345:                    break;
346:                case MDStatics.LONGW:
347:                case MDStatics.LONG:
348:                    data[0] = new Long(pk);
349:                    break;
350:                default:
351:                    throw BindingSupportImpl.getInstance().internal(
352:                            "Unhandled java type code: " + pkJavaTypeCode);
353:                }
354:            }
355:
356:            /**
357:             * Run SQL to get a new number. This does an update and a select for
358:             * our classes row in the keygen table.
359:             */
360:            protected int lookupNewNumber(Connection con, int effectiveGrabSize)
361:                    throws SQLException {
362:                PreparedStatement ps = null;
363:                try {
364:                    ps = con.prepareStatement(updateSql);
365:                    ps.setInt(1, effectiveGrabSize);
366:                    if (ps.executeUpdate() == 0) {
367:                        throw BindingSupportImpl.getInstance().fatalDatastore(
368:                                "Row not found in keygen table:\n" + updateSql);
369:                    }
370:                    Statement stat = null;
371:                    ResultSet rs = null;
372:                    try {
373:                        stat = con.createStatement();
374:                        rs = stat.executeQuery(selectSql);
375:                        rs.next();
376:                        return rs.getInt(1) - (effectiveGrabSize - 1);
377:                    } finally {
378:                        cleanup(rs);
379:                        cleanup(stat);
380:                    }
381:                } finally {
382:                    cleanup(ps);
383:                }
384:            }
385:
386:            private void cleanup(ResultSet rs) {
387:                try {
388:                    if (rs != null)
389:                        rs.close();
390:                } catch (SQLException e) {
391:                    // ignore
392:                }
393:            }
394:
395:            private void cleanup(Statement s) {
396:                try {
397:                    if (s != null)
398:                        s.close();
399:                } catch (SQLException e) {
400:                    // ignore
401:                }
402:            }
403:
404:            /**
405:             * Generate a new primary key value for a new instance of the supplied
406:             * class after the row has been inserted. The values generated will be used
407:             * to populate a new OID and then set on a PreparedStatement for the
408:             * insert.  This is called if isPostInsertGenerator returns true.
409:             *
410:             * @param className  The name of the class
411:             * @param classTable The table for the class
412:             * @param data       The array to store the key values in.
413:             * @param con        Connection to the DataSource for the class.
414:             * @param stat       Statement created from con. Do not close it. This will have
415:             *                   just been used to insert the new row.
416:             * @throws SQLException on errors
417:             */
418:            public void generatePrimaryKeyPost(String className,
419:                    JdbcTable classTable, Object[] data, Connection con,
420:                    Statement stat) throws SQLException {
421:                throw BindingSupportImpl.getInstance().internal(
422:                        "not a postInsertGenerator");
423:            }
424:
425:            /**
426:             * Get extra SQL to be appended to the insert statement. This is only
427:             * called for post insert key generators. Return null if no extra SQL
428:             * is required. Key generators can use this as an alternative to running
429:             * a separate query to get the primary key for the just inserted row.
430:             */
431:            public String getPostInsertSQLSuffix(JdbcTable classTable) {
432:                throw BindingSupportImpl.getInstance().internal(
433:                        "not a postInsertGenerator");
434:            }
435:
436:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.