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.util.Map<java.lang.String,java.util.Map<java.lang.Integer,java.util.Set<RecordIdentifier<java.lang.String>>>> |
cacheExtension
A cache extension allowing the look-up per table/multiplex faster
|
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 CentralLogger |
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 java.lang.String |
tenantId
The tenant that uses this session.
|
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.
|
|
Session(Database database,
DatabaseConfig cfg)
Construct the session and check out a pooled JDBC connection to use for its services.
|
private |
Session(Database database,
DatabaseConfig cfg,
boolean useCache,
DmoVersioning versioning,
java.lang.String tenantId)
Construct the session and check out a pooled JDBC connection to use for its services.
|
|
Session(Database database,
DatabaseConfig config,
DmoVersioning versioning,
java.lang.String tenantId)
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. |
| Modifier and Type | Method and Description |
|---|---|
private void |
addToCacheExtension(RecordIdentifier<java.lang.String> key,
BaseRecord dmo)
Make sure that the cache extension is consistent.
|
<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.
|
static void |
bootstrap()
Method called at server bootstrap that initializes values from the directory
configuration.
|
<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<FQLPreprocessor.SessionAttr> sessionAttrs,
int[] parPerm)
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.
|
(package private) boolean |
evictIfExist(java.lang.String dmoImplName,
long pk)
Evicts a record of a table specified by its DMO class implementation.
|
<T extends BaseRecord> |
get(java.lang.Class<T> dmoImplClass,
java.lang.Long id)
Gets a specified record of a table.
|
<T extends BaseRecord> |
get(java.lang.Class<T> dmoImplClass,
java.lang.Long id,
java.util.BitSet partialFields)
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,
java.util.BitSet partialFields)
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.
|
SavepointManager |
getSavepointManager()
Get the savepoint manager registered with this session, if any.
|
java.lang.String |
getTenantId()
Getter for the
tenantId field. |
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.
|
void |
lazilySetSavepoints()
Set the savepoint for the current block.
|
<T extends BaseRecord> |
merge(T dmo) |
<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.
|
private void |
removeFromCacheExtension(RecordIdentifier<java.lang.String> key,
BaseRecord dmo)
Make sure that the cache extension is consistent.
|
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.
|
void |
updateCachedRecords(java.lang.String dmoImplName,
java.lang.Integer multiplex,
java.util.function.Consumer<BaseRecord> update)
Apply the given update to all the cached records.
|
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 CentralLogger log
private final DmoVersioning versioning
private final Database database
private final Loader loader
private final Persister persister
private final java.lang.String tenantId
public static java.lang.String PK
p2j.cfg.xml)
for (conversion and) import process and in directory for normal execution.private ExpiryCache<RecordIdentifier<java.lang.String>,BaseRecord> cache
private java.util.Map<java.lang.String,java.util.Map<java.lang.Integer,java.util.Set<RecordIdentifier<java.lang.String>>>> cacheExtension
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, DatabaseConfig cfg) 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.cfg - The configuration for the given database.PersistenceException - if there is an error getting a JDBC connection from the data source.public Session(Database database, DatabaseConfig config, DmoVersioning versioning, java.lang.String tenantId) throws PersistenceException
This variant will construct a session with a built-in record cache.
database - Database with which to open a session.config - The configuration for the given database.versioning - Optional object which tracks record versions. May be null to disable versioning.tenantId - The id of the tenant.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, DatabaseConfig cfg, boolean useCache, DmoVersioning versioning, java.lang.String tenantId) throws PersistenceException
database - Database with which to open a session.cfg - The configuration for the given database.useCache - true to enable record caching; false to disable it.versioning - Optional object which tracks record versions. May be null to disable versioning.tenantId - The id of the tenant.PersistenceException - if there is an error getting a JDBC connection from the data source.public static void bootstrap()
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<FQLPreprocessor.SessionAttr> sessionAttrs, int[] parPerm)
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 queryparPerm - The permutation function, if any available.SQLQuery 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(java.lang.Class<T> dmoImplClass, java.lang.Long id, java.util.BitSet partialFields) 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.partialFields - For an incomplete record, read only these fields.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, java.util.BitSet partialFields) 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.partialFields - For an incomplete record, read only these fields.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 updateCachedRecords(java.lang.String dmoImplName,
java.lang.Integer multiplex,
java.util.function.Consumer<BaseRecord> update)
WARNING: this must be called only for temp-tables, and it must be used with a direct SQL on the same temp-table records, so that the cached and the sql table records have the same state.
work - The code to apply on the cached records.public void invalidateRecords(java.lang.String dmoImplName,
java.lang.Integer multiplex)
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.boolean evictIfExist(java.lang.String dmoImplName,
long pk)
dmoImplName - Name of the DMO implementation class whose associated records are going to be removed from
the cache.pk - The primary key of the record to be evicted.true if the record was evicted from cache and false is the specified record was
not found in cache.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 void lazilySetSavepoints()
throws PersistenceException
PersistenceExceptionpublic 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 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.AutoCloseablePersistenceException - 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()
public SavepointManager getSavepointManager()
null if none is registered.public java.lang.String getTenantId()
tenantId field.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 addToCacheExtension(RecordIdentifier<java.lang.String> key, BaseRecord dmo)
key - The key which was added to the primary cache.dmo - The dmo which was added. This is used to retrieve the multiplex.private void removeFromCacheExtension(RecordIdentifier<java.lang.String> key, BaseRecord dmo)
key - The key which is removed from the primary cache.dmo - The dmo which was removed. This is used to retrieve the multiplex.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.