Source Code Cross Referenced for SConnection.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.*;
004:        import java.util.HashMap;
005:        import java.util.Iterator;
006:
007:        /*
008:         * Copyright (c) 2002 Southern Cross Software Queensland (SCSQ).  All rights
009:         * reserved.  See COPYRIGHT.txt included in this distribution.
010:         */
011:
012:        /** Links JDBC Connections to SimpleORM ones and handles transacitons
013:         and flushing. <p>
014:        
015:         Associates existing JDBC transactions with the current thread so that
016:         they can be used by other SimpleORM classes.  Associating the
017:         connection with threads avoids nasty threading problems that can
018:         otherwise arrise.<p>
019:        
020:         SimpleORM takes no interest in how the JDBC connection was actually
021:         obtained.  It might be obtained directly using
022:         DriverManager.getConnection(), connection pooling software such as
023:         BitMechanic, or from a J2EE application server.  SimpleORM therefor
024:         does not restrict the environments in which it can be used.<P>
025:        
026:         But note that it is very important that transactions ONLY be COMMITED
027:         by SimpleORM class, and NOT by raw JDBC calls.<P>
028:        
029:         All transactions must start with a {@link #begin} and end with
030:         either a {@link #commit} or a {@link #rollback}.
031:         <code>commit</code> also {@link #flush}es any outsanding changes.
032:        
033:         (The complex AWT/Swing thread pattern is to have the main thread
034:         sets up the forms, and then exit.  A second AWT thread then does the
035:         real work.  In other words a single threaded application pointlessly
036:         using two threads!  SimpleORM works well with Swing but one needs to
037:         use <code>invokeAndWait()</code> to set up the forms the AWT thread,
038:         which is much cleaner anyway.  See 
039:         {@link simpleorm.examples.SwingTest} for an example.)<p>
040:        
041:         This is specialized by SConnectionEJB for use within JTA transaction management.
042:         **/
043:
044:        public class SConnection extends simpleorm.properties.SPropertyMap
045:                implements  SConstants {
046:            private static SThreadLocal threadSConnection = new SThreadLocal();
047:            private static long nrCons = 0;
048:
049:            Connection jdbcConnection = null;
050:            Connection jdbcSequenceConnection = null;
051:            SDriver sDriver = null;
052:
053:            /** The getMetaData() url.  Saved here so that toString can dispaly
054:             it even on a closed connection. */
055:            String url = null;
056:
057:            /** Transaction is active between begin and commit.*/
058:            boolean hasBegun = false;
059:
060:            /** Data has been flushed but not committed in this transaction. */
061:            boolean uncommittedFlushes = false;
062:
063:            /** Only to identify connection for toString() */
064:            long conNr = ++nrCons;
065:
066:            /** Provided by user to identify thread, eg. HTML session id.  Keep
067:             it short. */
068:            String name = "";
069:
070:            /** Of all records retrieved.  Both key and body are
071:             SRecordInstances, which has redefined equals() and hashTable(); */
072:            HashMap transactionCache = new HashMap();
073:
074:            /** Ordered list of SRecordInstances to flush and purge. */
075:            SArrayList updateList = new SArrayList(20);
076:
077:            /** Enables Extra internal validations throughout SimpleORM.  Cheap
078:             tests are always enabled, but this can be used to turn on tests
079:             that are expensive in times of trouble. */
080:            static boolean expensiveValidations = false;
081:
082:            /** No direct creation of Connections. */
083:            protected SConnection() {
084:            }
085:
086:            /** True iff commit must be called before the connection there are any (dirty) records that need to be
087:             committed, regardless of whether they have been flushed. 
088:             (Overriden in SConnectionEJB.)*/
089:            public boolean mustCommitBeforeDetaching() {
090:                return updateList.size() > 0 || uncommittedFlushes;
091:            }
092:
093:            /** Allows SConnection to be subclassed. 
094:             * connection should normally be null, in which case conf.obtainPrimaryJDBCConnection
095:             * is used to open it.
096:             * (rawConnection and sDriverName are deprecated.)
097:             */
098:            protected void innerAttach(SDataSource source,
099:                    String connectionName, Connection rawConnection,
100:                    SDriver driver) {
101:                name = connectionName;
102:
103:                SConnection badscon = getConnection();
104:                if (badscon != null)
105:                    throw new SException.Error(
106:                            "Thread's SConnection already open " + badscon);
107:
108:                dataSource = source;
109:                Connection con = rawConnection != null ? rawConnection
110:                        : dataSource.openPrimaryDBConnection();
111:                try {
112:                    if (con == null || con.isClosed())
113:                        throw new SException.Error("Connection " + con
114:                                + " is not open.");
115:                } catch (Exception ex) {
116:                    throw new SException.JDBC(ex);
117:                }
118:
119:                jdbcConnection = con;
120:                rawAttach();
121:
122:                try {
123:                    url = con.getMetaData().getURL();
124:                } catch (Exception eu) {
125:                    throw new SException.JDBC(eu);
126:                }
127:
128:                if (dataSource == null)
129:                    sDriver = driver == null ? SDriver.newSDriver(con, null)
130:                            : driver;
131:                else
132:                    sDriver = SDriver.newSDriver(con, dataSource
133:                            .getSDriverName());
134:                try {
135:                    if (jdbcConnection.getAutoCommit())
136:                        jdbcConnection.setAutoCommit(false);
137:                } catch (Exception ex) {
138:                    throw new SException.JDBC(ex);
139:                }
140:                String jvsn = SJSharp.jvmVersion();
141:                SLog.slog.connections("Attached Connection " + this 
142:                        + " SimpleORM " + SUte.simpleormVersion() + " jdk "
143:                        + jvsn);
144:            }
145:
146:            static SDataSource dataSource;
147:
148:            public SDataSource getDataSource() {
149:                return dataSource;
150:            }
151:
152:            protected void rawAttach() { // Overriden in SConnectionEJB
153:                threadSConnection.set(this );
154:            }
155:
156:            /** 
157:             * Attaches a SimpleORM connection to the current thread based on conf.
158:             * Opens a JDBC connection.<p>
159:             * 
160:             * connectionName is a simple name that can be used to identify this connection
161:             * in log traces etc.  Eg. the session ID plus the user name.  But keep it short
162:             * for logging.<p>
163:             * 
164:             * The driver is usually determined automatically (if null) based on the conf, 
165:             * but if it is overriden make sure to create a new driver instance for each connection.<p>
166:             * 
167:             * @see SDataSource for details.
168:             */
169:            public static void attach(SDataSource source, String connectionName) {
170:                new SConnection().innerAttach(source, connectionName, null,
171:                        null);
172:            }
173:
174:            /** Attaches the already opened JDBC Connection <code>con</code> to
175:             the current thread for future processing by SimpleORM.
176:             	 
177:             @deprecated Use attach() or attach(source) instead which can open mulitple connections needed for some key generation algorithms.
178:             @see SDataSource for details.
179:             */
180:            public static void attach(Connection con, String connectionName,
181:                    SDriver driver) {
182:                new SConnection()
183:                        .innerAttach(null, connectionName, con, driver);
184:            }
185:
186:            /** Attaches the already opened JDBC Connection <code>con</code> to
187:             the current thread for future processing by SimpleORM.
188:             	 
189:             @deprecated Use attach() or attach(source) instead which can open mulitple connections needed for some key generation algorithms.
190:             @see SDataSource for details.
191:             */
192:            public static void attach(Connection con, String connectionName) {
193:                new SConnection().innerAttach(null, connectionName, con, null);
194:            }
195:
196:            /** 
197:             * Retrieve or create the SConnection associated with this "Context".
198:             * Normally this just means (indirectly) call getThreadedConnection
199:             * which finds the connection associated with this thread.
200:             * However, if EJB.SConnectionEJB is loaded, then this can be dispached
201:             * to getTransactionConnection instead.   
202:             * <p>
203:             * 
204:             It may or may not be begun.  May be used to set properties for
205:             the connection, which persist between transactions but not
206:             between attach ments.*/
207:            static public SConnection getConnection() {
208:                return connectionGetter.getAConnection();
209:            }
210:
211:            static SConnection getThreadedConnection() {
212:                SConnection scon = (SConnection) threadSConnection.get();
213:                return scon;
214:            }
215:
216:            static protected ConnectionGetter connectionGetter = new ConnectionGetter();
217:
218:            /**
219:             * Just dispaches getConnection to either SConnection or SConnectionEJB if it was loaded.<p>
220:             * 
221:             * Normally connections are associated with the current thread and SConnectionEJB is not
222:             * a core part of SimpleORM and so not loaded.  
223:             * But if SConnectionEJB (or similar) is loaded then it has to be able to intercept
224:             * the SConnection.getConnection call used by all other SimpleORM methods such as 
225:             * findOrCreate.  So SConnectionEJB overrides the connectionGetter static when it loads 
226:             * so that it can redirect to itself, and then specialize SConnection methods as needed.<p>
227:             *   
228:             * Do not worry about this unless you are using EJB JTA.  
229:             * Note that this has nothing to do with the creation of jdbc connections.
230:             */
231:            protected static class ConnectionGetter {
232:                protected SConnection getAConnection() {
233:                    return SConnection.getThreadedConnection();
234:                }
235:            }
236:
237:            /** Gets current SConnection object for thread.  Throws an exception
238:             if not attached and open. */
239:            private static SConnection getOpenedConnection() {
240:                SConnection scon = getConnection();
241:                if (scon == null || scon.jdbcConnection == null)
242:                    throw new SException.Error(
243:                            "Bad SConnection -- Not opened/attached ");
244:                try {
245:                    if (expensiveValidations && scon.jdbcConnection.isClosed())
246:                        throw new SException.Error("Bad SConnection -- Closed "
247:                                + scon.jdbcConnection);
248:                } catch (Exception ex) {
249:                    throw new SException.JDBC(ex);
250:                }
251:                return scon;
252:            }
253:
254:            /** Gets current SConnection object for thread.  Throws an exception
255:             if not attached and open AND between begin() and
256:             commit() or rollback().  Package local.*/
257:            static SConnection getBegunConnection() {
258:                SConnection scon = getOpenedConnection();
259:                if (!scon.hasBegun())
260:                    throw new SException.Error("Transaction not begin()ed.");
261:                return scon;
262:            }
263:
264:            /** Transaction is active between begin and commit.*/
265:            public boolean hasBegun() {
266:                return hasBegun;
267:            }
268:
269:            /** If the JDBC connection has been attached and not closed. */
270:            public boolean isOpened() {
271:                try {
272:                    return jdbcConnection != null && !jdbcConnection.isClosed();
273:                } catch (SQLException ex) {
274:                    return false;
275:                }
276:            }
277:
278:            /** Asserts transaction Begin()ed and returns the JDBC connection.
279:             Can be used to integrate direct JDBC calls with the SimpleORM
280:             connection.  Dangerous.  Take care with caching and never use
281:             this to commit a transaction.  Should only be rarely used in
282:             practice. */
283:            public static Connection getBegunDBConnection() {
284:                SConnection scon = getBegunConnection();
285:                return scon.jdbcConnection;
286:            }
287:
288:            /**
289:             @deprecated Renamed to getBegunDB Connection (Might not beJDBC if .Net).
290:             */
291:            public static Connection getBegunJDBCConnection() {
292:                return getBegunDBConnection();
293:            }
294:
295:            /**
296:             * Returns a secondary jdbc connection for generating sequence numbers, if required.
297:             * Creates a new one if necessary. 
298:             */
299:            Connection getSequenceDBConnection() {
300:                if (jdbcSequenceConnection == null) {
301:                    if (getDataSource() == null)
302:                        throw new SException.Error(
303:                                "No SDataSource supplied to create secondary connection "
304:                                        + this );
305:                    jdbcSequenceConnection = getDataSource()
306:                            .openSecondaryDBConnection();
307:                }
308:                return jdbcSequenceConnection;
309:            }
310:
311:            /** Detaches the SConnection from the current thread without
312:             closing the JDBC connection so that it can be reattached to another thread. 
313:             Rarely used, <code>detachAndClose</code> is normally what is used.<p>
314:             
315:             Checks and throws and issues a message if there are any unflushed
316:             records that have been updated.  One should normally commit() or
317:             rollback() before detaching unless embedded within an EJB, in
318:             which flush() is required.
319:             */
320:            public static void detachWithoutClosing() {
321:                SConnection scon = getConnection();
322:                SLog.slog.connections("Detaching Connection " + scon);
323:                if (scon == null)
324:                    return; // Eg. if exception during long transaction.
325:                if (scon.hasBegun && scon.mustCommitBeforeDetaching()) {
326:                    // throw new SException.Error(...)
327:                    // Does not behave well in finally clauses -- if the try fails
328:                    // this then throws another "not committed" exception which masks
329:                    // the first. No known work arround in Java!
330:                    SLog.slog
331:                            .error("Transaction has unflushed updated records.  This is normally caused by an unrelated Exception throwing to the finally block in which case ignore this message.  But if no other exception then a commit() probably missing.");
332:                }
333:                destroyAll(); // For J2EE case where flush/detach used.
334:                scon.jdbcConnection = null;
335:                scon.jdbcSequenceConnection = null;
336:                scon.rawDetach();
337:            }
338:
339:            protected void rawDetach() { // Overriden in SConnectionEJB
340:                threadSConnection.set(null);
341:            }
342:
343:            /**
344:             * Closes the JDBC connection and then calls
345:             * <code>detachWithoutClosing</code> to detach the SimpleORM connection
346:             * from the current thread. Should usually be put in a finally clause. No
347:             * error if already detached or closed so safe in finally clauses.
348:             * <p>
349:             */
350:            public static void detachAndClose() {
351:                SConnection scon = getConnection();
352:                if (scon != null) {
353:                    closeCon(scon.jdbcConnection);
354:                    closeCon(scon.jdbcSequenceConnection);
355:                }
356:                detachWithoutClosing();
357:            }
358:
359:            private static void closeCon(Connection con) {
360:                boolean isOpen = false;
361:                try {
362:                    isOpen = con != null && !con.isClosed();
363:                } catch (Exception ex) {
364:                    throw new SException.JDBC("isClosed ", ex);
365:                }
366:                if (isOpen) {
367:                    try {
368:                        con.rollback(); // If transaction open and
369:                        // exception, esp. for DB2.
370:                    } catch (Exception ex) {
371:                        throw new SException.JDBC("Error rollback " + con, ex);
372:                    }
373:                    try {
374:                        con.close();
375:                    } catch (Exception ex) {
376:                        throw new SException.JDBC("Error closing " + con, ex);
377:                    }
378:                }
379:            }
380:
381:            /** Convenience routine for doing bulk updates using raw JDBC.
382:             Dangerous.  Take care with caching and never use this to commit
383:             a transaction.  Returns number of rows updated.
384:             Does nothing if sql == null.
385:             */
386:            public static int rawUpdateDB(String sql, Object[] params) {
387:                SLog.slog.updates("rawDB " + sql);
388:                int res = -1;
389:                if (sql != null) {
390:                    Connection con = getBegunDBConnection();
391:                    try {
392:                        PreparedStatement ps = con.prepareStatement(sql);
393:                        for (int px = 0; px < params.length; px++) {
394:                            ps.setObject(px + 1, params[px]);
395:                        }
396:                        res = ps.executeUpdate();
397:                        ps.close();
398:                    } catch (Exception ex) {
399:                        throw new SException.JDBC("SQL: " + sql, ex);
400:                    }
401:                }
402:                return res;
403:            }
404:
405:            public static int rawUpdateDB(String sql, Object param) {
406:                return rawUpdateDB(sql, new Object[] { param });
407:            }
408:
409:            public static int rawUpdateDB(String sql) {
410:                return rawUpdateDB(sql, new String[0]);
411:            }
412:
413:            /**
414:             @deprecated Renamed to rawUpdateDB Connection (Might not beJDBC).
415:             */
416:            public static int rawUpdateJDBC(String sql, Object[] params) {
417:                return rawUpdateDB(sql, params);
418:            }
419:
420:            /**
421:             @deprecated Renamed to rawUpdateDB Connection (Might not beJDBC).
422:             */
423:            public static int rawUpdateJDBC(String sql, Object param) {
424:                return rawUpdateDB(sql, param);
425:            }
426:
427:            /**
428:             @deprecated Renamed to rawUpdateDB Connection (Might not beJDBC).
429:             */
430:            public static int rawUpdateJDBC(String sql) {
431:                return rawUpdateDB(sql);
432:            }
433:
434:            /** Utility routine for dropping tables.  Hides JDBC exception
435:             caused if the table does not exist.  Mainly used in test cases.
436:             (Does not use the SRecord objects so that they do not all have
437:             to be loaded during specific tests.)  Dispatched to SDriver.<p>
438:             
439:             WARNING: JDBC error suppression is crude -- a table may indeed
440:             exist and still not be dropped for other reasons,
441:             eg. referential integrity. <p>
442:             
443:             WARNING: Due to bugs in JDBC etc. each dropped table must be in
444:             its own transaction in case of errors.  This routine commits changes.*/
445:            public static void dropTableNoError(String table) {
446:                if (getBegunConnection().mustCommitBeforeDetaching())
447:                    throw new SException.Error(
448:                            "Uncommited Updates need to be committed.");
449:                getDriver().dropTableNoError(table);
450:                commit();
451:                begin();
452:            }
453:
454:            /** Convenience routine for doing single row queries using raw JDBC.
455:             Be sure to flush the cache appropriately, or you will query
456:             behind it.<p>
457:             
458:             if <code>nrColumns == 0</code> (default) returns one result
459:             column as a non array object, otherwise returns an array of
460:             results.  (nrColumns avoids the need to use JDBC meta data which
461:             can be buggy.)  */
462:            public static Object rawQueryDB(String sql, String[] params,
463:                    int nrColumns) {
464:                Connection con = getBegunJDBCConnection();
465:                try {
466:                    PreparedStatement ps = con.prepareStatement(sql);
467:                    for (int px = 0; params != null && px < params.length; px++) {
468:                        ps.setString(px + 1, params[px]);
469:                    }
470:                    ResultSet rs = ps.executeQuery();
471:                    Object res = null;
472:                    if (rs.next()) {
473:                        if (nrColumns == 0)
474:                            res = rs.getObject(1);
475:                        else {
476:                            Object[] ares = new Object[nrColumns];
477:                            for (int rx = 0; rx < nrColumns; rx++)
478:                                ares[rx] = rs.getObject(rx + 1);
479:                            res = ares;
480:                        }
481:                        if (rs.next())
482:                            throw new SException.Error(
483:                                    "Query returned multiple rows " + sql
484:                                            + SUte.arrayToString(params));
485:                    }
486:                    rs.close();
487:                    ps.close();
488:                    if (SLog.slog.enableQueries())
489:                        SLog.slog.queries("rawJDBC " + sql + " -- " + res);
490:                    return res;
491:                } catch (Exception ex) {
492:                    throw new SException.JDBC(ex);
493:                }
494:            }
495:
496:            public static Object rawQueryDB(String sql, String[] params) {
497:                return rawQueryDB(sql, params, 0);
498:            }
499:
500:            public static Object rawQueryDB(String sql, String param) {
501:                return rawQueryDB(sql, new String[] { param });
502:            }
503:
504:            public static Object rawQueryDB(String sql) {
505:                return rawQueryDB(sql, new String[0]);
506:            }
507:
508:            /** @deprecated Renamed rawQueryDB  */
509:            public static Object rawQueryJDBC(String sql, String[] params,
510:                    int nrColumns) {
511:                return rawQueryDB(sql, params, nrColumns);
512:            }
513:
514:            public static Object rawQueryJDBC(String sql, String[] params) {
515:                return rawQueryDB(sql, params);
516:            }
517:
518:            public static Object rawQueryJDBC(String sql, String param) {
519:                return rawQueryDB(sql, param);
520:            }
521:
522:            public static Object rawQueryJDBC(String sql) {
523:                return rawQueryDB(sql);
524:            }
525:
526:            /** Start a new transaction.  A JDBC connection must already be
527:             attached to this thread, and must not be mid transaction. */
528:            public static void begin() {
529:                SConnection scon = getOpenedConnection();
530:                if (scon.hasBegun)
531:                    throw new SException.Error("Transaction already Begun.");
532:                if (scon.transactionCache.size() != 0
533:                        || scon.updateList.size() != 0)
534:                    throw new SException.InternalError(
535:                            "Non empty cache/update list.");
536:                scon.hasBegun = true;
537:                SLog.slog.connections("Begun Connection " + scon);
538:            }
539:
540:            /** Flush and purge the transaction cache to the database, and then
541:             commit the transaction.  Note that this is the only way that a
542:             transaction should be commited -- do not use JDBC commit
543:             directly.  Once commited, <code>begin()</code> must be used to
544:             start the next transaction.*/
545:            public static void commit() {
546:                SConnection scon = getBegunConnection();
547:                flush();
548:                destroyAll();
549:
550:                try {
551:                    scon.jdbcConnection.commit();
552:                } catch (Exception ex) {
553:                    throw new SException.JDBC(ex);
554:                }
555:                scon.uncommittedFlushes = false;
556:                scon.hasBegun = false;
557:                SLog.slog.connections("Committed Connection " + scon);
558:            }
559:
560:            /** Purges the cache and rolls back the transaction.  Any uncommited
561:             updates to the database are also rolled back. */
562:            public static void rollback() {
563:                destroyAll();
564:                SConnection scon = getBegunConnection();
565:                try {
566:                    scon.jdbcConnection.rollback();
567:                } catch (Exception ex) {
568:                    throw new SException.JDBC(ex);
569:                }
570:                scon.uncommittedFlushes = false;
571:                scon.hasBegun = false;
572:                SLog.slog.connections("Rolled Back Connection " + scon);
573:            }
574:
575:            /** Flush all records of tables in this transaction to the database. */
576:            public static void flush() {
577:                SConnection scon = getBegunConnection();
578:                for (int i = 0; i < scon.updateList.size(); i++) { // Jan reckons iterator causes grief?
579:                    SRecordInstance ri = (SRecordInstance) scon.updateList
580:                            .get(i);
581:                    if (ri != null)
582:                        ri.flush(); // Could have been manually flushed.
583:                }
584:                scon.updateList.clear();
585:            }
586:
587:            /** Flushes and Purges all record instances.  Can be used before a
588:             raw JDBC update to ensure that the cache remains consistent
589:             after the query.
590:             
591:             @see SRecordInstance#flushAndPurge
592:             @see SRecordMeta#flushAndPurge 
593:             */
594:            public static void flushAndPurge() {
595:                flush();
596:                destroyAll();
597:            }
598:
599:            /** Destroy all records in all tables so that they cannot be used
600:             again and to encourage garbage collection. */
601:            static void destroyAll() {
602:                SConnection scon = getConnection();
603:                Iterator ci = scon.transactionCache.values().iterator();
604:                while (ci.hasNext()) {
605:                    SRecordInstance ri = (SRecordInstance) ci.next();
606:                    ri.incompleteDestroy();
607:                }
608:                scon.transactionCache.clear();
609:                scon.updateList.clear();
610:            }
611:
612:            /** Dumps out the entire cache of records for this connection.  For
613:             debugging wierd bugs only. */
614:            public static void dumpCache() {
615:                SLog.slog.message("DumpCache");
616:                SConnection scon = getConnection();
617:                Iterator ci = scon.transactionCache.values().iterator();
618:                while (ci.hasNext()) {
619:                    SRecordInstance ri = (SRecordInstance) ci.next();
620:                    SLog.slog.message("  " + ri
621:                            + (ri.isDirty() ? " Dirty" : ""));
622:                }
623:            }
624:
625:            /** Eg. if (getDriver() instanceOf SDriverPostgres) ... 
626:             * Also getDriver().setMyFavoritePerConnectionParameter.
627:             */
628:            static public SDriver getDriver() {
629:                return getConnection().sDriver;
630:            }
631:
632:            /** Enables the SimpleORM connection to be disassociated with the
633:             current thread, and then associated with another thread.
634:             Dangerous.  When you pick up the connection you also pick up the
635:             hash map of records retrieved during the transaction.<p>
636:             
637:             This is provided for completeness only.  Note that both Swing
638:             and EJBs can be used without doing this (see the examples).  If
639:             you end up with two threads accessing the same connection at the
640:             same time you will have horrible, unreproduceable bugs.<p>
641:             
642:             Don not do it unless you really have to.  */
643:            public static SConnection unsafeDetachFromThread() {
644:                SConnection scon = (SConnection) threadSConnection.get();
645:                SLog.slog.connections("unsafeDetachFromThread " + scon);
646:                threadSConnection.set(null);
647:                return scon;
648:            }
649:
650:            /** Re-attacheds a detached connection to the current thread.
651:             
652:             @see #unsafeDetachFromThread
653:             */
654:            public void unsafeAttachToThread() {
655:                SConnection scon = (SConnection) threadSConnection.get();
656:                if (scon != null)
657:                    throw new SException.Error(
658:                            "This thread already has connection " + scon);
659:                threadSConnection.set(this );
660:                SLog.slog.connections("unsafeAttachToThread " + this );
661:            }
662:
663:            /** Short connection/thread identifier for inclusion in log messages
664:             to enable output from different threads to be separated. */
665:            static String shortToString() {
666:                SConnection con = getConnection();
667:                if (con != null)
668:                    return con.conNr + "." + con.name;
669:                else
670:                    return "No Connection";
671:            }
672:
673:            /*
674:             public static static void flush(Class rec){}
675:             public void flush(SRecordMeta rec){} // This record
676:             public static void purge(){} // ie. and remove from cache.
677:             public static void purge(Class rec){}
678:             public void purge(SRecordMeta rec){}
679:             */
680:
681:            public String toString() {
682:                return "[SConnection " + conNr + "_" + name + ": " + url + "]";
683:            }
684:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.