Source Code Cross Referenced for SRecordFinder.java in  » Database-ORM » SimpleORM » simpleorm » core » 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 » SimpleORM » simpleorm.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package simpleorm.core;
002:
003:        import java.sql.Connection;
004:        import java.sql.PreparedStatement;
005:        import java.sql.ResultSet;
006:
007:        import simpleorm.core.SException.InternalError;
008:        import simpleorm.core.SException.JDBC;
009:        import simpleorm.properties.SPropertyValue;
010:
011:        /**
012:         * Overflow of SRecordMeta code to retrieve records
013:         */
014:        class SRecordFinder {
015:
016:            /**
017:             * Implementation of SRecordMeta.findOrCreate
018:             */
019:            static SRecordInstance findOrCreate(SRecordMeta meta, Object key,
020:                    long sqy_bitSet, SFieldMeta[] selectList) {
021:                SConnection scon = SConnection.getBegunConnection();
022:
023:                boolean readOnly = SUte.inBitSet(sqy_bitSet,
024:                        SCon.SQY_READ_ONLY, SCon.SQY_);
025:                boolean unrepeatableRead = SUte.inBitSet(sqy_bitSet,
026:                        SCon.SQY_UNREPEATABLE_READ, SCon.SQY_);
027:                boolean optimistic = SUte.inBitSet(sqy_bitSet,
028:                        SCon.SQY_OPTIMISTIC, SCon.SQY_)
029:                        || (!scon.getDriver().supportsLocking() && !readOnly);
030:
031:                selectList = meta.expandSelectList(selectList);
032:
033:                if (SLog.slog.enableFields())
034:                    SLog.slog.fields("findOrCreate " + meta + " "
035:                            + SUte.arrayToString(key)
036:                            + (readOnly ? " ReadOnly" : "")
037:                            + (optimistic ? " Optimistic" : ""));
038:                if (readOnly && optimistic)
039:                    throw new SException.Error(
040:                            "Cannot be both Optimistically Locked and ReadOnly "
041:                                    + meta);
042:
043:                /// Create key object.  Discarded if found in cache.
044:                SRecordInstance keyInstance = null;
045:                try {
046:                    keyInstance = (SRecordInstance) meta.userClass
047:                            .newInstance();
048:                } catch (Exception ie) {
049:                    throw new SException.Data(ie);
050:                }
051:                setPrimaryKeys(keyInstance, key);
052:
053:                /// See if the record has already been retrieved in this transaction.
054:                SRecordInstance instance = (SRecordInstance) scon.transactionCache
055:                        .get(keyInstance);
056:
057:                boolean requery = false;
058:
059:                /// If previously retrieved then see if we need to requery.
060:                if (instance != null) {
061:                    instance.wasInCache = true;
062:                    /// See if we need to requery because there are extra fields.
063:                    // ### Need to recur if foreign keys.
064:                    requery = !readOnly && instance.readOnly;
065:                    for (int sx = 0; sx < selectList.length && !requery; sx++) {
066:                        SFieldMeta selF = selectList[sx];
067:                        byte selFSet = instance.bitSets[selF.fieldIndex];
068:                        requery = requery || ((selFSet & SCon.INS_VALID) == 0);
069:                        if (!readOnly)
070:                            requery = requery
071:                                    || ((selFSet & SCon.INS_READ_ONLY) != 0);
072:                    }
073:
074:                    if (SLog.slog.enableQueries())
075:                        SLog.slog.queries("findOrCreated: "
076:                                + instance
077:                                + " (from cache)"
078:                                + (instance.newRow ? " New Row"
079:                                        : " Existing Row")
080:                                + (requery ? " Requerying..." : ""));
081:                    if (instance.sConnection != scon)
082:                        throw new SException.Error("Inconsistent Connections "
083:                                + instance + instance.sConnection + scon);
084:                } else
085:                    keyInstance.wasInCache = false;
086:
087:                /// (re)Query the database
088:                if (instance == null || requery) {
089:                    instance = findInDatabase(meta,
090:                            instance != null ? instance : keyInstance, // If requery
091:                            sqy_bitSet, selectList, scon, readOnly, optimistic,
092:                            unrepeatableRead, null); // ### Need to bring out this props parameter.
093:                    if (SLog.slog.enableQueries())
094:                        SLog.slog.queries("findOrCreate: "
095:                                + instance
096:                                + " (from database)"
097:                                + (instance.newRow ? " New Row"
098:                                        : " Existing Row"));
099:
100:                    if (instance.newRow)
101:                        validatePrimaryKeys(instance); // Could throw SValidationException
102:
103:                    scon.transactionCache.put(instance, instance);
104:                    // equals() is defined below
105:                    instance.sConnection = scon;
106:                }
107:                if (instance.getMeta() != meta)
108:                    throw new SException.InternalError("Found " + instance
109:                            + " instead of " + meta);
110:                return instance;
111:            }
112:
113:            /** Sets just the primary key fields, used to lookup
114:             transactionCache.  See equals(). <p>
115:             
116:             For foreign keys, <code>pkeys</code> only contains the reference
117:             object, not the foreign keys themselves.<p>
118:             
119:             Primary keys are not set dirty.
120:             */
121:            static void setPrimaryKeys(SRecordInstance inst, Object pkey) {
122:                /// If keys is a single key then make it an singleton array.
123:                Object[] npkeys = null;
124:                int keylen = 1;
125:                if (pkey instanceof  Object[]) {
126:                    npkeys = (Object[]) pkey;
127:                    keylen = npkeys.length;
128:                }
129:                SRecordMeta meta = inst.getMeta();
130:                int kx = -1;
131:                for (int mx = 0; mx < meta.keySFieldMetas.size(); mx++) {
132:                    SFieldMeta keyf = (SFieldMeta) meta.keySFieldMetas.get(mx);
133:                    if (keyf.sFieldReference == null) { // Top level only
134:                        kx++;
135:
136:                        if (keylen < kx + 1)
137:                            throw new SException.Data("Too few key params "
138:                                    + SUte.arrayToString(pkey));
139:
140:                        Object rawValue = npkeys != null ? npkeys[kx] : pkey;
141:                        if (rawValue == null)
142:                            throw new SException.Data("Null Primary key "
143:                                    + keyf + " " + kx);
144:
145:                        /// Convert rawValue if necessary.
146:                        Object convValue = null;
147:                        try {
148:                            convValue = keyf.convertToField(rawValue);
149:                        } catch (Exception ex) {
150:                            throw new SException.Data("Converting " + rawValue
151:                                    + " for " + inst + "." + keyf, ex);
152:                        }
153:
154:                        // For references this will also copy the foreign key values.
155:                        //SLog.slog.debug("setPrimaryKey " + keyf + this + convValue);
156:                        keyf.rawSetFieldValue(inst, convValue);
157:                    }
158:                }
159:                if (kx + 1 != keylen)
160:                    throw new SException.Error("Too many key params "
161:                            + (kx + 1) + " < " + SUte.arrayToString(pkey)
162:                            + ".length");
163:            }
164:
165:            /** Look up the database for a record with keys that are now in
166:             <code>instance</code> and populate <code>instance</code>
167:             appropriately.*/
168:            static private SRecordInstance findInDatabase(SRecordMeta meta,
169:                    SRecordInstance instance, long sqy_bitSet,
170:                    SFieldMeta[] selectList, SConnection scon,
171:                    boolean readOnly, boolean optimistic,
172:                    boolean unrepeatableRead, SPropertyValue[] props) {
173:
174:                //System.out.println("findInDatabase " + meta + SLog.arrayToString(selectList));
175:                boolean existing = false;
176:                if (SUte
177:                        .inBitSet(sqy_bitSet, SCon.SQY_ASSUME_CREATE, SCon.SQY_)) {
178:                    existing = false;
179:                } else {
180:                    /// Determine the SQL Query
181:                    String qry = scon.sDriver.selectSQL(selectList, meta,
182:                            meta.fieldList(SCon.SQY_PRIMARY_KEY
183:                                    | SCon.SQY_NO_REFERENCES), // for WHERE
184:                            null, !readOnly && !optimistic, unrepeatableRead,
185:                            null);
186:
187:                    if (SLog.slog.enableQueries())
188:                        SLog.slog.queries("findOrCreate querying '" + qry
189:                                + "'...");
190:
191:                    /// Prepare the statement
192:                    Connection con = scon.jdbcConnection;
193:                    PreparedStatement ps = null;
194:                    ResultSet rs = null;
195:                    try {
196:                        try {
197:                            ps = con.prepareStatement(qry); // Let the JDBC driver cache these.
198:                        } catch (Exception psex) {
199:                            throw new SException.JDBC(
200:                                    "Preparing '" + qry + "'", psex);
201:                        }
202:                        /// Set the primary key
203:                        int qkx = 0;
204:                        for (int kx = 0; kx < meta.keySFieldMetas.size(); kx++) {
205:                            SFieldMeta key = (SFieldMeta) meta.keySFieldMetas
206:                                    .get(kx);
207:                            if (!(key instanceof  SFieldReference)) {
208:                                qkx++;
209:                                Object value = instance.fieldValues[key.fieldIndex];
210:                                try {
211:                                    ps.setObject(qkx, value);
212:                                } catch (Exception se) {
213:                                    throw new SException.JDBC(
214:                                            "Setting preQuery " + instance
215:                                                    + "'" + qry + "' Field "
216:                                                    + qkx + " to " + value, se);
217:                                }
218:                            }
219:                        }
220:                        /// Execute the Query
221:                        try {
222:                            rs = ps.executeQuery();
223:                        } catch (Exception rsex) {
224:                            throw new SException.JDBC("Executing '" + qry
225:                                    + "' for " + instance, rsex);
226:                        }
227:
228:                        /// Retrieve the result.
229:                        try {
230:                            existing = rs.next();
231:                        } catch (Exception ne1) {
232:                            throw new SException.JDBC("Nexting " + instance,
233:                                    ne1);
234:                        }
235:                        if (existing) {
236:                            SRecordFinder.retrieveRecord(instance, selectList,
237:                                    rs, readOnly, optimistic, true);
238:                            boolean next = false;
239:                            try {
240:                                next = rs.next();
241:                            } catch (Exception ne2) {
242:                                throw new SException.JDBC(ne2);
243:                            }
244:                            if (next)
245:                                throw new SException.JDBC(
246:                                        "Primary key not unique " + instance);
247:                        }
248:                    } finally {
249:                        try {
250:                            if (rs != null)
251:                                rs.close();
252:                        } catch (Exception cl1) {
253:                            throw new SException.JDBC("Closing rs " + instance,
254:                                    cl1);
255:                        }
256:                        try {
257:                            if (ps != null)
258:                                ps.close();
259:                        } catch (Exception clp) {
260:                            throw new SException.JDBC("Closing ps " + instance,
261:                                    clp);
262:                        }
263:                    }
264:                }
265:
266:                if (!existing) { // not in database
267:                    instance.newRow = true;
268:                    instance.readOnly = readOnly;
269:                    /// Make all fields settable.
270:                    // (Need to do this so still setable after a flush())
271:                    // New rows have a hard gettable default of null.
272:                    for (int ifx = 0; ifx < meta.sFieldMetas.size(); ifx++) {
273:                        SFieldMeta iff = (SFieldMeta) meta.sFieldMetas.get(ifx);
274:                        //if ( !iff.getBoolean( SMANDATORY ) )
275:                        instance.bitSets[iff.fieldIndex] |= SCon.INS_VALID;
276:                    }
277:                }
278:
279:                // Null the primary-key references, since they may be detached
280:                // references, which does not make sense in an attached instance.
281:                // (A subsequent getReference would do a findOrCreate.)
282:                //
283:                // ##Bartek. I think this is now redundant given getRawFieldValue suppresses
284:                // references to detached records.
285:                for (int ifx = 0; ifx < meta.sFieldMetas.size(); ifx++) {
286:                    if (meta.sFieldMetas.get(ifx) instanceof  SFieldReference) {
287:                        SRecordInstance keyr = (SRecordInstance) instance.fieldValues[ifx];
288:                        if (keyr != null
289:                                && (!keyr.isValid() || !keyr.isAttached()))
290:                            instance.fieldValues[ifx] = null;
291:                    }
292:                }
293:
294:                return instance;
295:            } // findInDatabase
296:
297:            /**
298:             * Map SRecordInstance.validateField for all primary keys.
299:             * This is only called for newly created records, not for each find,
300:             * which is why it needs to be done in a different pass.
301:             */
302:            static void validatePrimaryKeys(SRecordInstance inst) {
303:                /// If keys is a single key then make it an singleton array.
304:                SRecordMeta meta = inst.getMeta();
305:                for (int mx = 0; mx < meta.keySFieldMetas.size(); mx++) {
306:                    SFieldMeta keyf = (SFieldMeta) meta.keySFieldMetas.get(mx);
307:                    if (keyf.sFieldReference == null) { // Top level only
308:                        Object valu = keyf.getFieldValue(inst, 0);
309:                        inst.validateField(keyf, valu);
310:                    }
311:                }
312:            }
313:
314:            /** Called from SRecordMeta and SResultSet to acutally retrieve the
315:             record.  <code>selectList</code> includes primary key fields.
316:             Calls <code>SField*.queryVieldValue</code> to actually
317:             retrieve the values.*/
318:            static void retrieveRecord(SRecordInstance instance,
319:                    SFieldMeta[] selectList, ResultSet rs, boolean readOnly,
320:                    boolean optimistic, boolean checkPrimaryKey) {
321:                /// Retrieve each fieldValue[]
322:                for (int fx = 0; fx < selectList.length; fx++) {
323:                    SFieldMeta fMeta = selectList[fx];
324:                    int ffx = fMeta.fieldIndex;
325:                    Object qvalue = null;
326:                    try {
327:                        qvalue = fMeta.queryFieldValue(rs, fx + 1);
328:                    } catch (Exception ge) {
329:                        throw new SException.JDBC("Getting Field " + (fx + 1)
330:                                + " from " + instance, ge);
331:                    }
332:                    if (checkPrimaryKey && fMeta.isPrimaryKey)
333:                        if (qvalue == null
334:                                || !trimStringEquals(qvalue,
335:                                        instance.fieldValues[ffx]))
336:                            throw new SException.InternalError("Bad PKey "
337:                                    + qvalue.getClass() + " '" + qvalue
338:                                    + "' !equal() '"
339:                                    + instance.fieldValues[ffx].getClass()
340:                                    + "' " + instance.fieldValues[ffx]);
341:                    // ## This is dubious.  What if they are the same except for trailing spaces?
342:                    // This test will pass, but in general the records will not be considered the same
343:                    // as we do not generally trim spaces.
344:                    // See SRecordInstance.getString.
345:                    instance.fieldValues[ffx] = qvalue;
346:                    instance.readOnly = readOnly;
347:                    if (readOnly
348:                            && (instance.bitSets[ffx] & SCon.INS_VALID) == 0)
349:                        // If it has previously been retrieved for update do not set ReadOnly now.
350:                        instance.bitSets[ffx] |= SCon.INS_READ_ONLY;
351:                    else if (!readOnly)
352:                        instance.bitSets[ffx] &= ~SCon.INS_READ_ONLY;
353:                    instance.bitSets[ffx] |= SCon.INS_VALID;
354:                }
355:
356:                /// Update instance flags
357:                instance.readOnly = readOnly;
358:                if (optimistic)
359:                    instance.setOptimistic(false);
360:            }
361:
362:            /** returns first.rightTrim.equals.rightTrim(second) */
363:            static private boolean trimStringEquals(Object firstObj,
364:                    Object secondObj) {
365:                if (!(firstObj instanceof  String))
366:                    return firstObj.equals(secondObj);
367:                String first = (String) firstObj, second = (String) secondObj;
368:                if (second == null)
369:                    return false;
370:                int fx = first.length() - 1, sx = second.length() - 1;
371:                boolean trimed = false;
372:                for (; fx > -1 && first.charAt(fx) == ' '; fx--)
373:                    trimed = true;
374:                for (; sx > -1 && second.charAt(sx) == ' '; sx--)
375:                    trimed = true;
376:                if (fx != sx)
377:                    return false;
378:                if (!trimed)
379:                    return first.equals(second); // Optimization
380:                for (; fx > -1; fx--)
381:                    if (first.charAt(fx) != second.charAt(fx))
382:                        return false;
383:                return true;
384:            }
385:
386:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.