Class SSessionJdbc

  • Direct Known Subclasses:
    PersistenceSession

    public class SSessionJdbc
    extends SSessionI
    Performs all the interactions between a DataSet and a JDBC Connection.

    SSessionJdbc.open creates a new session and associates it with the current thread.

    All transactions must start with a begin(), which normally creates a new DataSet to store records in. They with either a commit() or a rollback() which normally destroy the DataSet and all records in it. commit also flush()es any outsanding changes.

    Methods are then provided to retrieve recrods from the databse by primary key or general query.

    There are also convenience method for performing raw SQL queries should that be required.

    • Constructor Detail

      • SSessionJdbc

        protected SSessionJdbc()
        No direct creation of Connections.
    • Method Detail

      • open

        public static SSessionJdbc open​(javax.sql.DataSource source,
                                        java.lang.String connectionName,
                                        SDriver driver)
        Attaches a SimpleORM connection to the current thread based on conf. Opens a JDBC connection.

        connectionName is a simple name that can be used to identify this connection in log traces etc. Eg. the session ID plus the user name. But keep it short for logging.

        The driver is usually determined automatically (if null) based on the conf, but if it is overriden make sure to create a new driver instance for each connection.

        See TestUte.java for an example of how to create a trivial DataSource from an old style DriverManager

      • open

        public static SSessionJdbc open​(javax.sql.DataSource source,
                                        java.lang.String connectionName)
      • innerOpen

        protected void innerOpen​(javax.sql.DataSource source,
                                 java.lang.String connectionName,
                                 SDriver driver)
        Allows SSession to be subclassed. connection should normally be null, in which case conf.obtainPrimaryJDBCConnection is used to open it. (rawConnection and sDriverName are deprecated.)

        We use DataSource rather than just Connection to allow a driver to create a second connection to generate keys etc. But that has never been used, and some old code that potentially supported it has been removed.

      • associateWithThread

        protected void associateWithThread()
      • dissassociateFromThread

        protected void dissassociateFromThread()
      • getThreadLocalSession

        public static SSessionJdbc getThreadLocalSession()
        Retrieve or create the SSession associated with this "Context". Normally this just means (indirectly) call getThreadedConnection which finds the connection associated with this thread.

        (In extras there is an unsupported EJB.SConnectionEJB class which dispached to getTransactionConnection instead.)

        It may or may not be begun. May be used to set properties for the connection, which persist between transactions but not between attach ments.

        This is never used within SimpleOrm itself, it is just a convenience method for users.

      • close

        public void close()
        Main method for closing a session.

        Closes the JDBC connection and then calls detachWithoutClosing to detach the SimpleORM connection from the current thread. Should usually be put in a finally clause. No error if already detached or closed so safe in finally clauses.

      • detachFromThread

        public SSessionJdbc detachFromThread()
        Enables the SimpleORM connection to be disassociated with the current thread, and then possibly attached to another thread. It also enables multiple sessions to be used within the same thread without getting mixed thread exceptions. (But not multiple threads to use the same session concurrently.)

        Rarely used, normally better to just create a session in the appropriate thread. Both Swing and EJBs can be used without doing this.

        Do not not do it unless you really have to.

      • attachToThread

        public void attachToThread()
        Re-attacheds a detached connection to the current thread.
        See Also:
        detachFromThread()
      • getDataSource

        public javax.sql.DataSource getDataSource()
      • begin

        public void begin()
        Start a new transaction. A JDBC connection must already be attached to this thread, and must not be mid transaction.
      • begin

        public void begin​(SDataSet ds)
        Begin a new transaction based on a previously detached data set
      • hasBegun

        public boolean hasBegun()
        Transaction is active between begin and commit.
      • commit

        public void commit()
        Flush and purge the transaction cache to the database, and then commit the transaction. Note that this is the only way that a transaction should be committed -- do not use JDBC commit directly. Once committed, begin() must be used to start the next transaction.

        Also closes any open SResultSets and SPreparedStatements

      • commitAndDetachDataSet

        public SDataSet commitAndDetachDataSet()
      • rollback

        public void rollback()
        Purges the cache and rolls back the transaction. Any uncommited updates to the database are also rolled back.

        Also closes any open SResultSets and SPreparedStatements

      • setTransactionIsolation

        public void setTransactionIsolation​(int mode)
        Set the transaction isolation mode. SimpleORM does not normally change the isolation mode, but consider setting it to Connection.TRANSACTION_SERIALIZABLE to achieve greater reliability in many databases.
        Parameters:
        mode - as defined by java.sql.Connection.setTransactionIsolation
      • flush

        public void flush()
        Flush all records of tables in this transaction to the database.
      • flush

        public void flush​(SRecordInstance instance)
        Flush this instance to the database. Normally called by SSession.flush() in reponse to commit but can also be called expicitly if the update order needs to be modified. This method does nothing unless the record is dirty.

        See Also:
        SSession#flush
      • flushAndPurge

        public void flushAndPurge​(SRecordInstance ri)
        Flushes this record instance to the database, removes it from the transaction cache, and then destroys the record so that it can no longer be used. Any future findOrCreate will requery the data base and produce a new record.

        This is useful if one wants to do raw JDBC updates on the record, and be guaranteed not to have an inconsistent cache. (Where bulk updates can be used they are several times faster than updates made via the JVM -- see the benchmarks section in the white paper.)

        It can also be useful to force a requery of records if optmistic locks are being broken, although care must be taken not to rely on values returned by a outdated query.

        See Also:
        SSession#flush
      • flushAndPurge

        public void flushAndPurge()
        Flushes and Purges all record instances. Can be used before a raw JDBC update to ensure that the cache remains consistent after the query.
        See Also:
        SRecordInstance#flushAndPurge, SRecordMeta#flushAndPurge
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
      • query

        public <RI extends SRecordInstance> java.util.List<RI> query​(SQuery<RI> qry)
        Execute the query and return a list of records. First always flushes any dirty records to the database. (Flush but not commit.)
      • queryOnlyRecord

        public <RI extends SRecordInstance> RI queryOnlyRecord​(SQuery<RI> qry)
        Same as query but throws an exception if there is more than one record returned.
      • find

        public <RI extends SRecordInstance> RI find​(SRecordMeta<RI> rmeta,
                                                    SQueryMode queryMode,
                                                    java.lang.Object... keys)
        Same as findOrCreate but if not existing returns null rather than creating a new record. (Note that it may still need to query the database to determine if it is not there.)
      • create

        public <RI extends SRecordInstance> RI create​(SRecordMeta<RI> rmeta,
                                                      java.lang.Object... keys)
        Create a new record.

        Assumes the record is new, will do an insert at flush time which will cause a unique index violation if it was not. Use a findOrCreate followed by assertNewRow if it is unclear whether the row is really new.

      • createWithGeneratedKey

        public <RI extends SRecordInstance> RI createWithGeneratedKey​(SRecordMeta<RI> rmeta)
        Creates a new object with a newly generated key. Note that the SELECT MAX method is used unless a database dependent alternative is available (currently only for PostgreSQL). SGENERATED_KEY.

        Always creates a new empty record. ## This code is partially copied into SRecordInstance.attach() for records created while detached.

      • dirtyPurge

        public void dirtyPurge​(SRecordInstance rinst)
        Removes this record from the cache but without flushing it. Any changes to it will be lost. This might be useful if the record is being manually updated/deleted and you want to deliberately ignore any direct changes.

        Dangerous, use with care.

        See Also:
        flushAndPurge(simpleorm.dataset.SRecordInstance)
      • rawUpdateDB

        public int rawUpdateDB​(java.lang.String sql,
                               java.lang.Object... params)
        Convenience routine for doing bulk updates using raw JDBC. Dangerous. Take care with caching and never use this to commit a transaction. Returns number of rows updated. Does nothing if sql == null.

        Flushes before performing update. But does not requery any updated records.

      • rawUpdateDBNoFlush

        public int rawUpdateDBNoFlush​(java.lang.String sql,
                                      java.lang.Object... params)
      • rawQueryMaps

        public java.util.List<java.util.Map> rawQueryMaps​(java.lang.String sql,
                                                          boolean flush,
                                                          java.lang.Object... params)
        Executes sql with parameters, returns a list of Maps of values, one map per row. The key to the maps is the meta data returned by JDBC. This is normally just the column name, but can be specified in most SQLs. eg.

        SELECT MAX(SALARY) AS MAX_SAL ... FROM ....

      • rawQueryMap

        public java.util.Map rawQueryMap​(java.lang.String sql,
                                         boolean flush,
                                         java.lang.Object... params)
        Returns at most one row, else exception. Null if none.
      • rawQueryOneMap

        public java.util.Map rawQueryOneMap​(java.lang.String sql,
                                            boolean flush,
                                            java.lang.Object... params)
        Returns exactly one row, else exception. Exception if none.
      • rawQuerySingle

        public java.lang.Object rawQuerySingle​(java.lang.String sql,
                                               boolean flush,
                                               java.lang.Object... params)
        Returns a single value of at most one row.
      • getLogger

        public SLog getLogger()
      • getJdbcConnection

        public java.sql.Connection getJdbcConnection()
      • getDataSet

        public SDataSet getDataSet()
      • getDriver

        public SDriver getDriver()
        Eg. if (getDriver() instanceOf SDriverPostgres) ... Also getDriver().setMyFavoritePerConnectionParameter.