public class Session extends java.lang.Object implements DmoState, CacheExpiryListener<RecordIdentifier<java.lang.String>,BaseRecord>, java.lang.AutoCloseable
The lifetime of a session object and the JDBC connection it uses are the same. Once the JDBC connection which backs a session instance is closed, the session can no longer be used. If a new connection is needed, a new session must be created.
Modifier and Type | Field and Description |
---|---|
private java.lang.Boolean |
batch
Lazy flag indicating whether the JDBC data store supports batch operations
|
private ExpiryCache<RecordIdentifier<java.lang.String>,BaseRecord> |
cache
Cache of database records associated with this session
|
private java.sql.Connection |
conn
Active JDBC connection, opened when session is instantiated, closed when it is closed
|
private Database |
database
Database with which this session is used
|
static java.lang.String |
DEFAULT_PK
The default name of the primary key.
|
private boolean |
inTx
Flag indicating whether a transaction currently is open
|
private Loader |
loader
Helper used to load records from the database
|
private static java.util.logging.Logger |
log
Logger
|
private Persister |
persister
Helper used to persist records to the database
|
static java.lang.String |
PK
The primary key name in use.
|
private SavepointManager |
savepointManager
Active savepoint manager, if any
|
private int |
txCount
Count of transactions opened during this session's lifetime
|
private DmoVersioning |
versioning
Object which tracks the current versions of DMOs to enable stale checking
|
Modifier | Constructor and Description |
---|---|
|
Session(Database database)
Construct the session and check out a pooled JDBC connection to use for its services.
|
private |
Session(Database database,
boolean useCache,
DmoVersioning versioning)
Construct the session and check out a pooled JDBC connection to use for its services.
|
|
Session(Database database,
javax.sql.DataSource ds)
Construct the session and check out a JDBC connection from a specified
DataSource to
use for its services. |
|
Session(Database database,
DmoVersioning versioning)
Construct the session and check out a pooled JDBC connection to use for its services.
|
Modifier and Type | Method and Description |
---|---|
<T extends BaseRecord> |
associate(RecordIdentifier<java.lang.String> key,
T dmo)
Associate the given record with the session cache.
|
<T extends BaseRecord> |
associate(T dmo)
Associate the given record with the session cache.
|
boolean |
beginTransaction()
Begin a new database transaction, if one does not already exist for this session.
|
boolean |
beginTransaction(SavepointManager savepointManager)
Begin a new database transaction, if one does not already exist for this session.
|
<T extends BaseRecord> |
bulkSave(java.util.List<T> records)
Persist a list of records, performing inserts using SQL batching, if supported.
|
void |
cacheExpired(CacheExpiryEvent<RecordIdentifier<java.lang.String>,BaseRecord> event)
This method is invoked when the session cache has expired one or more elements.
|
private void |
checkClosed()
Test whether the connection is alive (not closed).
|
private <T extends BaseRecord> |
checkStale(RecordIdentifier<java.lang.String> key,
T dmo)
If DMO versioning is enabled for this session, check whether the given record is stale.
|
private void |
checkTx()
A sanity check to ensure any DML being executed is performed within an active transaction or on an
auto-commit connection.
|
void |
clear()
Clear the session DMO cache.
|
void |
close()
Closes the connection to database and invalidates the local field.
|
boolean |
commit()
Commit all work done since the beginning of the current transaction.
|
private ExpiryCache<RecordIdentifier<java.lang.String>,BaseRecord> |
createCache()
Create a session expiry cache which disallows DMOs which are referenced by buffers or which are being
tracked for UNDO purposes from being expired.
|
static Query |
createQuery(java.util.function.Consumer<Query> cache,
java.lang.String fql)
Creates and returns a
Query based on a FQL statement. |
static Query |
createQuery(java.lang.String fql)
Creates and returns a
Query based on a FQL statement. |
static SQLQuery |
createSQLQuery(java.lang.String sql)
Creates and returns a
SQLQuery based on a SQL statement (not mandatory a SQL query). |
static SQLQuery |
createSQLQuery(java.lang.String sql,
java.util.List<HQLPreprocessor.SessionAttr> sessionAttrs)
Creates and returns a
SQLQuery based on a SQL statement (not mandatory a SQL query). |
boolean |
delete(java.lang.String entity,
java.lang.Long id)
Deletes a record from the database and from internal cache.
|
<T extends BaseRecord> |
delete(T dmo)
Delete the DMO's record(s) from the database and remove it from the cache.
|
private void |
deregisterVersioned()
Deregister any cached records from DMO version tracking.
|
void |
disableCache()
Disables cache for this session.
|
private void |
evict(RecordIdentifier<java.lang.String> key,
BaseRecord dmo)
Remove a record from the session cache.
|
<T extends BaseRecord> |
evict(T dmo)
Remove a record from the session cache.
|
<T extends BaseRecord> |
get(java.lang.Class<T> dmoImplClass,
java.lang.Long id)
Gets a specified record of a table.
|
<T extends BaseRecord> |
get(RecordIdentifier<java.lang.String> key)
Gets a specified record of a table.
|
<T extends BaseRecord> |
get(java.lang.String entity,
java.lang.Long id)
Get a record.
|
<T extends BaseRecord> |
getCached(java.lang.Class<T> dmoClass,
java.lang.Long id)
Get the cached DMO of the given type with the given primary key.
|
private <T extends BaseRecord> |
getCached(RecordIdentifier<java.lang.String> key)
Get the cached DMO associated with the given primary key, if any.
|
java.sql.Connection |
getConnection()
Convenience method to access this session database connection.
|
Database |
getDatabase()
Obtain the FWD database this session serves.
|
private <T extends BaseRecord> |
getImpl(java.lang.Class<T> dmoImplClass,
java.lang.Long id,
RecordIdentifier<java.lang.String> key)
Get a record.
|
static RecordMeta |
getMetadata(java.lang.Class<? extends BaseRecord> dmoClass)
Get the record metadata for the given DMO implementation class.
|
(package private) Persister |
getPersister()
Get the persister for this session.
|
(package private) SavepointManager |
getSavepointManager()
Get the savepoint manager registered with this session, if any.
|
java.lang.Long |
getTxNestingId()
Get the zero-based transaction block nesting level, where 0 indicates the current block is a full
transaction block, 1 indicates the current block is the first level of nested subtransaction, and so
on.
|
boolean |
inTransaction()
Indicate whether a database transaction currently is in process.
|
void |
invalidateRecords(java.lang.String dmoImplName,
java.lang.Integer multiplex)
Invalidates all records from cache belonging to a specific table.
|
boolean |
isOpen()
Test if the connection to database is active / open.
|
<T extends BaseRecord> |
merge(T dmo) |
void |
noUndoBulkUpdate(Query query)
Create a redoable SQL operation for the bulk update of zero or more NO-UNDO records in
the database.
|
void |
noUndoBulkUpdate(SQLQuery query)
Create a redoable SQL operation for the bulk update of zero or more NO-UNDO records in
the database.
|
<T extends BaseRecord> |
refresh(T dmo)
Refresh the given DMO with data from the database, bypassing the cache.
|
void |
releaseSavepoint(java.sql.Savepoint savepoint)
Release the given savepoint, thereby disabling the ability to roll back to the point at
which it was created.
|
boolean |
rollback()
Roll back all work done since the beginning of the current transaction.
|
boolean |
rollbackSavepoint(java.sql.Savepoint savepoint)
Roll back all database changes since the given savepoint was set.
|
<T extends BaseRecord> |
save(T dmo,
boolean updateDmoState)
Saves a
dmo to database. |
java.sql.Savepoint |
setSavepoint()
Set a savepoint to which database changes can be rolled back, if we are currently within an active
transaction.
|
(package private) boolean |
supportsBatch()
Indicate whether the JDBC driver used by this session supports batch statement operations.
|
void |
trackUndoable(BaseRecord dmo)
Begin tracking an undoable record as needing savepoint processing.
|
public static final java.lang.String PK
p2j.cfg.xml
)
for (conversion and) import process and in directory for normal execution.public static final java.lang.String DEFAULT_PK
SchemaConfig.primaryKeyName
, used at conversion and
import time. The default "recid" is a reserved keyword in 4GL, so it cannot conflict with an
existing field/column name.private static final java.util.logging.Logger log
private final DmoVersioning versioning
private final Database database
private final Loader loader
private final Persister persister
private ExpiryCache<RecordIdentifier<java.lang.String>,BaseRecord> cache
private java.sql.Connection conn
private boolean inTx
private SavepointManager savepointManager
private java.lang.Boolean batch
private int txCount
public Session(Database database) throws PersistenceException
This variant will construct a session which does not have a built-in record cache.
database
- Database with which to open a session.PersistenceException
- if there is an error getting a JDBC connection from the data source.public Session(Database database, DmoVersioning versioning) throws PersistenceException
This variant will construct a session with a built-in record cache.
database
- Database with which to open a session.versioning
- Optional object which tracks record versions. May be null
to disable versioning.PersistenceException
- if there is an error getting a JDBC connection from the data source.public Session(Database database, javax.sql.DataSource ds) throws PersistenceException
DataSource
to
use for its services.database
- Database with which to open a session.ds
- The DataSource
that will provide the connection to database.PersistenceException
- if there is an error getting a JDBC connection from the data source.private Session(Database database, boolean useCache, DmoVersioning versioning) throws PersistenceException
database
- Database with which to open a session.useCache
- true
to enable record caching; false
to disable it.versioning
- Optional object which tracks record versions. May be null
to disable versioning.PersistenceException
- if there is an error getting a JDBC connection from the data source.public static Query createQuery(java.lang.String fql)
Query
based on a FQL statement. The returned object is not
bounded to any session; the Session
upon which it will be executed will be provided
at the time of execution.fql
- The FQL statement that will be executed by the returned Query
.SQLQuery
that can be used to execute the specified SQL statement.public static Query createQuery(java.util.function.Consumer<Query> cache, java.lang.String fql)
Query
based on a FQL statement. The returned object is not
bounded to any session; the Session
upon which it will be executed will be provided
at the time of execution.cache
- caching lambdafql
- The FQL statement that will be executed by the returned Query
.SQLQuery
that can be used to execute the specified SQL statement.public static SQLQuery createSQLQuery(java.lang.String sql, java.util.List<HQLPreprocessor.SessionAttr> sessionAttrs)
SQLQuery
based on a SQL statement (not mandatory a SQL query).
The returned object is not bounded to any connection; the Connection
upon which it
will be executed will be provided at the time of execution.sql
- The SQL statement that will be executed by the returned SQLQuery
.sessionAttrs
- Mutable session attributes' values used in the querySQLQuery
that can be used to execute the specified SQL statement.public static SQLQuery createSQLQuery(java.lang.String sql)
SQLQuery
based on a SQL statement (not mandatory a SQL query).
The returned object is not bounded to any connection; the Connection
upon which it
will be executed will be provided at the time of execution.sql
- The SQL statement that will be executed by the returned SQLQuery
.SQLQuery
that can be used to execute the specified SQL statement.public static RecordMeta getMetadata(java.lang.Class<? extends BaseRecord> dmoClass)
dmoClass
- DMO implementation class.java.lang.IllegalArgumentException
- if the DMO class does not define a record metadata field or if there is an error
accessing it.public <T extends BaseRecord> T getCached(java.lang.Class<T> dmoClass, java.lang.Long id) throws PersistenceException
If a record is found in the cache, but it is marked stale, it is removed.
dmoClass
- DMO implementation type.id
- Primary key.null
if it was not cached under the given
primary key or if it was marked stale.PersistenceException
- if a DMO instance is found in the cache which is not of the given DMO type.public <T extends BaseRecord> T get(java.lang.Class<T> dmoImplClass, java.lang.Long id) throws PersistenceException
null
is returned. If the record was fetched from the
database at this moment, it is kept in cache for further access.T
- The type of the record.dmoImplClass
- The class of the entity (class that implements the table's DMO interface).id
- The id/rowid of the record to be returned.null
otherwise.PersistenceException
- In case some error occurs in the process.public <T extends BaseRecord> T get(RecordIdentifier<java.lang.String> key) throws PersistenceException
null
is returned. If the record was fetched from the
database at this moment, it is kept in cache for further access.T
- The type of the record.key
- The record identifier key with which the DMO is associated in the cache. The table
portion of the key must be the fully qualified class name of the DMO.null
otherwise.PersistenceException
- In case some error occurs in the process.public <T extends BaseRecord> T get(java.lang.String entity, java.lang.Long id) throws PersistenceException
null
is returned.T
- The compile type of the record to be returned.entity
- The string representation of the Class
of the entity to be returned.id
- The recid
of the entity to be returned.null
otherwise.PersistenceException
- if there is an error getting a JDBC connection from the data source.private <T extends BaseRecord> T getImpl(java.lang.Class<T> dmoImplClass, java.lang.Long id, RecordIdentifier<java.lang.String> key) throws PersistenceException
null
is returned.T
- The compile type of the record to be returned.dmoImplClass
- The class of the entity (class that implements the table's DMO interface). Optional if a valid
key
is provided.id
- The recid
of the entity to be returned. Optional if a valid key
is provided.key
- The cache key of the entity. If null
the returned value is null
;
provided.null
otherwise.PersistenceException
- if there is an error getting a JDBC connection from the data source.public <T extends BaseRecord> void save(T dmo, boolean updateDmoState) throws PersistenceException
dmo
to database. If so requested, its internal state information is updated.T
- The compile type of the record.dmo
- The record to be saved.updateDmoState
- If true
its internal state information is updated. This is the standard
call. When the method is called for validation, use false
as the database
operation will be rolled back anyway, so the state must not be altered.PersistenceException
- When an exception is encountered. Must be analyzed as the cause might be expected
(ex: when validating a record).StaleRecordException
- if the record being saved is stale.public <T extends BaseRecord> int bulkSave(java.util.List<T> records) throws PersistenceException
This method is not intended for legacy runtime support. It is meant for bulk inserts and as such, it:
records
- List of records to be saved. Each record must have a unique, positive primary key
assigned.PersistenceException
- if there was an error performing the batch insert. This will wrapper the SQLException
thrown by the JDBC layer.public <T extends BaseRecord> boolean delete(T dmo) throws PersistenceException
T
- DMO typedmo
- DMO to be deleted.true
on successPersistenceException
- if there is a database error, or if a different DMO instance with the same ID as
the given DMO is found in cache.public boolean delete(java.lang.String entity, java.lang.Long id) throws PersistenceException
NOTE: Only used by dirty share manager; currently not integrated with the savepoint manager, due to inability to discern between undoable and NO-UNDO records
entity
- The string representation of the Class
of the record to be deleted.
Actually, this represents the table of the record to be deleted.id
- The recid
of the record to be deleted.true
if the record wa found and deleted and false
if the record was
not detected in database.PersistenceException
- if there is an error accessing the database.java.lang.IllegalArgumentException
- if id
is null.public void invalidateRecords(java.lang.String dmoImplName, java.lang.Integer multiplex)
TODO: this is a terribly inefficient algorithm. We scan the entire contents of the cache and compare table name strings of each entry to find a subset of records (possibly none). If it is used often, we need a better caching strategy to support this use case.
dmoImplName
- Name of the DMO implementation class whose associated records are going to be removed from
the cache.multiplex
- Optional multiplex used to filter which records are deleted.public <T extends BaseRecord> T refresh(T dmo) throws PersistenceException
null
is returned.dmo
- DMO whose data is to be refreshed from the database.dmo
, containing refreshed data,
or null
if a matching record was not found.PersistenceException
- if a database error occurs.public <T extends BaseRecord> T merge(T dmo) throws PersistenceException
T
- dmo TYPEdmo
- DMOPersistenceException
- on errorpublic <T extends BaseRecord> void associate(T dmo) throws PersistenceException, StaleRecordException
dmo
- The record to associate with the cache.PersistenceException
- if another record instance already is associated with the session under the same key.StaleRecordException
- if the record being associated with the session is stale.public <T extends BaseRecord> void associate(RecordIdentifier<java.lang.String> key, T dmo) throws PersistenceException, StaleRecordException
key
- The record identifier key with which to associate the record in the cache. The table
portion of the key must be the fully qualified class name of the DMO.dmo
- The record to associate with the cache.PersistenceException
- if another record instance already is associated with the session under the same key.StaleRecordException
- if the record being associated with the session is stale.public <T extends BaseRecord> void evict(T dmo)
T
- The compile type of the record.dmo
- The record to be evicted.public java.sql.Connection getConnection() throws PersistenceException
Use with caution and do not directly commit, rollback, set or release savepoints, etc.!
Definitely do not close this connection directly! This will render the enclosing session
inoperable. Use the Session
API for these services instead.
PersistenceException
- if the JDBC connection has been closed or there was an error checking its status.public boolean inTransaction()
true
if a transaction exists, else false
.public boolean beginTransaction() throws PersistenceException
true
if a new transaction was begun; false
if a transaction
already exists for this session.PersistenceException
- if a database error occurs.public boolean beginTransaction(SavepointManager savepointManager) throws PersistenceException
savepointManager
- Optional savepoint manager to install in the session for the duration of the
transaction. This should only be installed when the transaction corresponds with
a legacy, application-level transaction. It will match database savepoints with
application block sub-transactions, and keep in-memory DMO state in sync with
the database through commit and rollback processing. Should be null
when
beginning a database transaction which does not correspond with a legacy
application transactionstrue
if a new transaction was begun; false
if a transaction
already exists for this session.PersistenceException
- if a database error occurs.public boolean commit() throws PersistenceException
The session's current savepoint manager, if any, is discarded after the transaction ends.
true
if the transaction was committed; false
if it there is no
active transaction to commit.PersistenceException
- if there was a database error committing the transaction.public boolean rollback() throws PersistenceException
The session's current savepoint manager, if any, is discarded after the transaction ends.
true
if the transaction was rolled back; false
if it there is no
active transaction to roll back.PersistenceException
- if there was a database error rolling back the transaction.public java.sql.Savepoint setSavepoint() throws PersistenceException
null
is returned if we are not within
an active transaction.PersistenceException
- if a database error occurs.public void releaseSavepoint(java.sql.Savepoint savepoint) throws PersistenceException
savepoint
- The savepoint to be released.PersistenceException
- if a database error occurs.public boolean rollbackSavepoint(java.sql.Savepoint savepoint) throws PersistenceException
savepoint
- Savepoint to which changes should be rolled back.false
if we are not in a transaction when this method is invoked;
true
if we are in a transaction and the rollback was successful.PersistenceException
- if a database error occurs.public boolean isOpen()
true
if the connection to database is usable.public void clear() throws PersistenceException
PersistenceException
- on errorpublic void disableCache() throws PersistenceException
PersistenceException
- on errorpublic void noUndoBulkUpdate(Query query)
This method delegates to the session's savepoint manager, if any, whose responsibility it is to track and apply the corresponding redoable SQL operation at the appropriate moment.
query
- FQL query which performed the original bulk operation.public void noUndoBulkUpdate(SQLQuery query)
This method delegates to the session's savepoint manager, if any, whose responsibility it is to track and apply the corresponding redoable SQL operation at the appropriate moment.
query
- SQL query which performed the original bulk operation.public java.lang.Long getTxNestingId()
public void trackUndoable(BaseRecord dmo) throws PersistenceException
dmo
- Record to be tracked.PersistenceException
- if there is an error lazily setting associated savepoints in the savepoint manager.SavepointManager.trackUndoable(BaseRecord)
public void close() throws PersistenceException
close
in interface java.lang.AutoCloseable
PersistenceException
- in the event of an error.public Database getDatabase()
Database
this session is attached to.public void cacheExpired(CacheExpiryEvent<RecordIdentifier<java.lang.String>,BaseRecord> event)
Important: Delivery of this event is not asynchronous, so any delay in this method's return will impact the performance of the cache! This implementation should be maintained to return as quickly as possible.
cacheExpired
in interface CacheExpiryListener<RecordIdentifier<java.lang.String>,BaseRecord>
event
- An object containing information about the event.boolean supportsBatch() throws PersistenceException
true
if batch operations are supported, else false
.PersistenceException
- if database metadata needs to be queried and there is an error doing so.private <T extends BaseRecord> T getCached(RecordIdentifier<java.lang.String> key) throws PersistenceException
If a record is found in the cache, but it is stale, it is removed.
key
- The record identifier key with which the DMO is associated in the cache. The table
portion of the key must be the fully qualified class name of the DMO.null
if there is no cache, if the record was not cached
under the given primary key, or if the record was determined to be stale.PersistenceException
- if a DMO instance is found in the cache which is not of the given DMO type.Persister getPersister()
SavepointManager getSavepointManager()
null
if none is registered.private ExpiryCache<RecordIdentifier<java.lang.String>,BaseRecord> createCache()
private void evict(RecordIdentifier<java.lang.String> key, BaseRecord dmo)
key
- The record identifier key with which the DMO is associated in the cache. The table
portion of the key must be the fully qualified class name of the DMO.dmo
- The record to be evicted.private void deregisterVersioned()
private void checkClosed() throws PersistenceException
PersistenceException
is thrown.PersistenceException
- when the connection is not usable because it was closed.private void checkTx() throws PersistenceException
TODO: the conditions for which this method checks represent programming errors and as such, we may want to remove this method once the persistence subsystem is well tested. On the other hand, the overhead is quite low: in the common case, there is just the overhead of the method call itself and of an instance field check.
PersistenceException
- if we are not in an active transaction and the connection is not set to auto-commit.private <T extends BaseRecord> void checkStale(RecordIdentifier<java.lang.String> key, T dmo) throws StaleRecordException
dmo
- Record to be checked.StaleRecordException
- if the record is stale.