Source Code Cross Referenced for TableMapping.java in  » Database-ORM » Persist » net » sf » persist » Java Source Code / Java DocumentationJava Source Code and Java Documentation

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


001:        // $Id: TableMapping.java 15 2007-09-01 03:09:40Z jcamaia $
002:
003:        package net.sf.persist;
004:
005:        import java.lang.reflect.Method;
006:        import java.sql.DatabaseMetaData;
007:        import java.sql.ResultSet;
008:        import java.sql.SQLException;
009:        import java.util.ArrayList;
010:        import java.util.Collection;
011:        import java.util.HashSet;
012:        import java.util.LinkedHashMap;
013:        import java.util.List;
014:        import java.util.Locale;
015:        import java.util.Map;
016:        import java.util.Set;
017:
018:        /**
019:         * Holds mapping data from a given class and a table
020:         */
021:        public final class TableMapping extends Mapping {
022:
023:            private final Class objectClass;
024:
025:            private final net.sf.persist.annotations.Table tableAnnotation;
026:            private final String tableName;
027:
028:            private final String[] fields; // list of fields which have getters and setters
029:            private final Map<String, net.sf.persist.annotations.Column> annotationsMap; // maps field names to annotations
030:            private final Map<String, Method> gettersMap; // maps field names to getters
031:            private final Map<String, Method> settersMap; // maps field names to setters
032:
033:            private final boolean supportsGetGeneratedKeys;
034:            private final boolean supportsBatchUpdates;
035:
036:            private final Map<String, String> columnsMap = new LinkedHashMap(); // maps table columns to property names
037:            private final String[] columns;
038:            private final String[] primaryKeys;
039:            private final String[] notPrimaryKeys;
040:            private final String[] autoGeneratedColumns;
041:            private final String[] notAutoGeneratedColumns;
042:
043:            private final String selectSql;
044:            private final String selectAllSql;
045:            private final String insertSql;
046:            private final String updateSql;
047:            private final String deleteSql;
048:
049:            public TableMapping(final DatabaseMetaData metaData,
050:                    final Class objectClass, final NameGuesser nameGuesser)
051:                    throws SQLException {
052:
053:                ResultSet resultSet = null;
054:
055:                // object class
056:                this .objectClass = objectClass;
057:
058:                // database support for auto increment keys
059:                supportsGetGeneratedKeys = metaData.supportsGetGeneratedKeys();
060:
061:                // database support for batch updates
062:                supportsBatchUpdates = metaData.supportsBatchUpdates();
063:
064:                // database name
065:                final String databaseProductName = metaData
066:                        .getDatabaseProductName();
067:
068:                // table annotation
069:                tableAnnotation = (net.sf.persist.annotations.Table) objectClass
070:                        .getAnnotation(net.sf.persist.annotations.Table.class);
071:
072:                // schema pattern
073:                String schemaPattern = null;
074:                if (databaseProductName.equalsIgnoreCase("Oracle")) {
075:                    schemaPattern = "%"; // oracle expects a pattern such as "%" to work
076:                }
077:
078:                // table name and annotation
079:                tableName = getTableName(metaData, schemaPattern, objectClass,
080:                        nameGuesser);
081:
082:                // all column names and types (from db)
083:
084:                final List<String> columnsList = new ArrayList();
085:                resultSet = metaData.getColumns(null, schemaPattern, tableName,
086:                        "%");
087:                while (resultSet.next()) {
088:                    final String columnName = resultSet.getString(4);
089:                    columnsList.add(columnName);
090:                }
091:                columns = toArray(columnsList);
092:
093:                // all primary keys (from db)
094:
095:                final List<String> primaryKeysList = new ArrayList();
096:                resultSet = metaData.getPrimaryKeys(null, schemaPattern,
097:                        tableName);
098:                while (resultSet.next()) {
099:                    final String columnName = resultSet.getString(4);
100:                    primaryKeysList.add(columnName);
101:                }
102:                primaryKeys = toArray(primaryKeysList);
103:
104:                // not primary keys
105:
106:                final List<String> notPrimaryKeysList = new ArrayList();
107:                for (String columnName : columns) {
108:                    if (!primaryKeysList.contains(columnName)) {
109:                        notPrimaryKeysList.add(columnName);
110:                    }
111:                }
112:                notPrimaryKeys = toArray(notPrimaryKeysList);
113:
114:                // map field names to annotations, getters and setters
115:
116:                final Map[] fieldsMaps = getFieldsMaps(objectClass);
117:                annotationsMap = fieldsMaps[0];
118:                gettersMap = fieldsMaps[1];
119:                settersMap = fieldsMaps[2];
120:                fields = toArray(gettersMap.keySet());
121:
122:                // map column names to field names; create list of auto-increment columns
123:                // columnsMap use keys in lower case
124:
125:                // the actual autoGeneratedColumns list should have columns in the database order
126:                final Set<String> autoGeneratedColumnsTemp = new HashSet();
127:                for (String fieldName : fields) {
128:                    final String columnName = getColumnName(objectClass,
129:                            nameGuesser, annotationsMap, columnsList,
130:                            tableName, fieldName);
131:                    columnsMap.put(columnName.toLowerCase(Locale.ENGLISH),
132:                            fieldName);
133:                    final net.sf.persist.annotations.Column annotation = annotationsMap
134:                            .get(fieldName);
135:                    if (annotation != null && annotation.autoGenerated()) {
136:                        autoGeneratedColumnsTemp.add(columnName);
137:                    }
138:                }
139:
140:                // auto-increment and not-auto-increment columns, in the database order
141:
142:                final List<String> notAutoGeneratedColumnsList = new ArrayList();
143:                final List<String> autoGeneratedColumnsList = new ArrayList();
144:                for (String columnName : columns) {
145:                    if (autoGeneratedColumnsTemp.contains(columnName)) {
146:                        autoGeneratedColumnsList.add(columnName);
147:                    } else {
148:                        notAutoGeneratedColumnsList.add(columnName);
149:                    }
150:                }
151:                notAutoGeneratedColumns = toArray(notAutoGeneratedColumnsList);
152:                autoGeneratedColumns = toArray(autoGeneratedColumnsList);
153:
154:                // assemble sql blocks to be used by crud sql statements
155:
156:                final String allColumns = join(columns, "", ",");
157:                final String noAutoColumns = join(notAutoGeneratedColumns, "",
158:                        ",");
159:                final String allPlaceholders = multiply("?", columns.length,
160:                        ",");
161:                final String noAutoPlaceholders = multiply("?",
162:                        notAutoGeneratedColumns.length, ",");
163:                final String where = join(primaryKeys, "=?", ",");
164:                final String updateSet = join(notPrimaryKeys, "=?", ",");
165:
166:                // assemble crud sql statements
167:
168:                selectSql = "select " + allColumns + " from " + tableName
169:                        + " where " + where;
170:                selectAllSql = "select " + allColumns + " from " + tableName;
171:
172:                if (autoGeneratedColumns.length == 0) {
173:                    insertSql = "insert into " + tableName + "(" + allColumns
174:                            + ")values(" + allPlaceholders + ")";
175:                } else {
176:                    insertSql = "insert into " + tableName + "("
177:                            + noAutoColumns + ")values(" + noAutoPlaceholders
178:                            + ")";
179:                }
180:
181:                updateSql = "update " + tableName + " set " + updateSet
182:                        + " where " + where;
183:                deleteSql = "delete from " + tableName + " where " + where;
184:
185:            }
186:
187:            // ---------- getters and setters ----------
188:
189:            public boolean supportsGetGeneratedKeys() {
190:                return supportsGetGeneratedKeys;
191:            }
192:
193:            public boolean supportsBatchUpdates() {
194:                return supportsBatchUpdates;
195:            }
196:
197:            public Class getObjectClass() {
198:                return objectClass;
199:            }
200:
201:            public String getTableName() {
202:                return tableName;
203:            }
204:
205:            public net.sf.persist.annotations.Table getTableAnnotation() {
206:                return tableAnnotation;
207:            }
208:
209:            public String[] getColumns() {
210:                return columns;
211:            }
212:
213:            public Map<String, String> getColumnsMap() {
214:                return columnsMap;
215:            }
216:
217:            public String[] getPrimaryKeys() {
218:                return primaryKeys;
219:            }
220:
221:            public String[] getNotPrimaryKeys() {
222:                return notPrimaryKeys;
223:            }
224:
225:            public String[] getAutoGeneratedColumns() {
226:                return autoGeneratedColumns;
227:            }
228:
229:            public String[] getNotAutoGeneratedColumns() {
230:                return notAutoGeneratedColumns;
231:            }
232:
233:            public String[] getFields() {
234:                return fields;
235:            }
236:
237:            public Map<String, net.sf.persist.annotations.Column> getAnnotationsMap() {
238:                return annotationsMap;
239:            }
240:
241:            public Map<String, Method> getGettersMap() {
242:                return gettersMap;
243:            }
244:
245:            public Map<String, Method> getSettersMap() {
246:                return settersMap;
247:            }
248:
249:            public Method getGetterForColumn(final String columnName) {
250:                final String fieldName = columnsMap.get(columnName
251:                        .toLowerCase(Locale.ENGLISH));
252:                return gettersMap.get(fieldName);
253:            }
254:
255:            public Method getSetterForColumn(final String columnName) {
256:                final String fieldName = columnsMap.get(columnName
257:                        .toLowerCase(Locale.ENGLISH));
258:                return settersMap.get(fieldName);
259:            }
260:
261:            public String getSelectSql() {
262:                return selectSql;
263:            }
264:
265:            public String getSelectAllSql() {
266:                return selectAllSql;
267:            }
268:
269:            public String getInsertSql() {
270:                return insertSql;
271:            }
272:
273:            public String getUpdateSql() {
274:                return updateSql;
275:            }
276:
277:            public String getDeleteSql() {
278:                return deleteSql;
279:            }
280:
281:            // ---------- utility methods ----------
282:
283:            private static String getTableName(final DatabaseMetaData metaData,
284:                    final String schema, final Class objectClass,
285:                    final NameGuesser nameGuesser) throws SQLException {
286:
287:                String name = null;
288:
289:                final net.sf.persist.annotations.Table tableAnnotation = (net.sf.persist.annotations.Table) objectClass
290:                        .getAnnotation(net.sf.persist.annotations.Table.class);
291:
292:                if (tableAnnotation != null
293:                        && !tableAnnotation.name().equals("")) {
294:                    // if there's a Table annotation, use it
295:                    name = checkTableName(metaData, schema, tableAnnotation
296:                            .name());
297:
298:                    // test if the specified table name actually exists
299:                    if (name == null) {
300:                        throw new PersistException("Class ["
301:                                + objectClass.getName() + "] specifies table ["
302:                                + tableAnnotation.name()
303:                                + "] that does not exist in the database");
304:                    }
305:                } else {
306:                    // if no annotation, try guessed table names
307:                    final String className = objectClass.getSimpleName()
308:                            .substring(0, 1).toLowerCase()
309:                            + objectClass.getSimpleName().substring(1);
310:                    final Set<String> guessedNames = nameGuesser
311:                            .guessColumn(className);
312:                    for (String guessedTableName : guessedNames) {
313:                        name = checkTableName(metaData, schema,
314:                                guessedTableName);
315:                        if (name != null) {
316:                            break;
317:                        }
318:                    }
319:                    if (name == null) {
320:                        throw new PersistException(
321:                                "Class ["
322:                                        + objectClass.getName()
323:                                        + "] does not specify a table name through a Table annotation and no guessed table names "
324:                                        + guessedNames
325:                                        + " exist in the database");
326:                    }
327:                }
328:
329:                return name;
330:            }
331:
332:            /**
333:             * Check if the given name corresponds to a table in the database and
334:             * returns the corresponding name with the capitalization returned by the
335:             * database metadata
336:             */
337:            private static String checkTableName(
338:                    final DatabaseMetaData metaData, final String schema,
339:                    final String tableName) throws SQLException {
340:
341:                ResultSet resultSet;
342:                String ret = null;
343:
344:                // try name in upper case -- should work in most databases
345:                resultSet = metaData.getTables(null, schema, tableName
346:                        .toUpperCase(Locale.ENGLISH), null);
347:                if (resultSet.next()) {
348:                    ret = tableName.toUpperCase(Locale.ENGLISH);
349:                }
350:                resultSet.close();
351:
352:                if (ret == null) {
353:                    // try name in lower case
354:                    resultSet = metaData.getTables(null, schema, tableName
355:                            .toLowerCase(Locale.ENGLISH), null);
356:                    if (resultSet.next()) {
357:                        ret = tableName.toLowerCase(Locale.ENGLISH);
358:                    }
359:                    resultSet.close();
360:                }
361:
362:                if (ret == null) {
363:                    // last resort: compare with all table names in the schema 
364:                    // (may be very expensive in databases such as oracle)
365:                    // this may end up being used in databases that allow case sensitive names (such as postgresql)
366:                    resultSet = metaData.getTables(null, schema, "%", null);
367:                    while (resultSet.next()) {
368:                        final String dbTableName = resultSet.getString(3);
369:                        if (tableName.equalsIgnoreCase(dbTableName)) {
370:                            ret = dbTableName;
371:                            break;
372:                        }
373:                    }
374:                    resultSet.close();
375:                }
376:
377:                return ret;
378:            }
379:
380:            private static String getColumnName(
381:                    final Class objectClass,
382:                    final NameGuesser nameGuesser,
383:                    final Map<String, net.sf.persist.annotations.Column> annotationsMap,
384:                    final List<String> columnsList, final String tableName,
385:                    final String fieldName) throws SQLException {
386:
387:                String columnName = null;
388:
389:                final net.sf.persist.annotations.Column annotation = annotationsMap
390:                        .get(fieldName);
391:                if (annotation != null && !annotation.name().equals("")) {
392:                    // if there's an annotation, use it
393:                    columnName = getIgnoreCase(columnsList, annotation.name());
394:
395:                    // check if the specified column actually exists in the table
396:                    if (columnName == null) {
397:                        throw new PersistException("Field [" + fieldName
398:                                + "] from class [" + objectClass.getName()
399:                                + "] specifies column [" + annotation.name()
400:                                + "] on table ["
401:                                + tableName.toLowerCase(Locale.ENGLISH)
402:                                + "] that does not exist in the database");
403:                    }
404:                } else {
405:                    // if no annotation, try guessed column names
406:                    final Set<String> guessedNames = nameGuesser
407:                            .guessColumn(fieldName);
408:                    for (String guessedColumnName : guessedNames) {
409:                        columnName = getIgnoreCase(columnsList,
410:                                guessedColumnName);
411:                        if (columnName != null) {
412:                            break;
413:                        }
414:                    }
415:                    if (columnName == null) {
416:                        throw new PersistException(
417:                                "Field ["
418:                                        + fieldName
419:                                        + "] from class ["
420:                                        + objectClass.getName()
421:                                        + "] does not specify a column name through a Column annotation and no guessed column names "
422:                                        + guessedNames
423:                                        + " exist in the database. If this field is not supposed to be associated "
424:                                        + "with the database, please annotate it with @NoColumn");
425:                    }
426:                }
427:
428:                return columnName;
429:            }
430:
431:            // ---------- helpers ----------
432:
433:            /**
434:             * Returns the first entry from the provided collection that matches the
435:             * provided string ignoring case during the comparison.
436:             */
437:            private static String getIgnoreCase(
438:                    final Collection<String> collection, final String str) {
439:                String ret = null;
440:                for (String s : collection) {
441:                    if (s.equalsIgnoreCase(str)) {
442:                        ret = s;
443:                        break;
444:                    }
445:                }
446:                return ret;
447:            }
448:
449:            private static String[] toArray(final List<String> list) {
450:                String[] array = new String[list.size()];
451:                for (int i = 0; i < list.size(); i++) {
452:                    array[i] = list.get(i);
453:                }
454:                return array;
455:            }
456:
457:            private static String[] toArray(final Set<String> set) {
458:                final String[] array = new String[set.size()];
459:                int i = 0;
460:                for (String s : set) {
461:                    array[i] = s;
462:                    i++;
463:                }
464:                return array;
465:            }
466:
467:            private static String join(final String[] list,
468:                    final String suffix, final String separator) {
469:                final StringBuffer buf = new StringBuffer();
470:                for (String obj : list) {
471:                    buf.append(obj.toString()).append(suffix).append(separator);
472:                }
473:                if (buf.length() > 0 && separator.length() > 0) {
474:                    buf.delete(buf.length() - separator.length(), buf.length());
475:                }
476:                return buf.toString();
477:            }
478:
479:            private static String multiply(final String str, final int times,
480:                    final String separator) {
481:                final StringBuffer buf = new StringBuffer();
482:                for (int i = 0; i < times; i++) {
483:                    buf.append(str).append(separator);
484:                }
485:                if (separator.length() > 0) {
486:                    buf.delete(buf.length() - separator.length(), buf.length());
487:                }
488:                return buf.toString();
489:            }
490:
491:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.