public final class OptCounterInfo
extends java.lang.Object
implements java.lang.Cloneable, java.io.Serializable
This class contains information about the value of the OPTCOUNTER column for a row in a database table.
The OptCounterInfo class defines four properties:
true" if the CurrentValue matches the value in the database,
and so it can be included in a WHERE clause. A value that has been incremented
or randomized does not need to be included in the WHERE clause. It is
assumed that an increment or randomize operation is only performed when a
database write lock has been obtained.
true"
if the CurrentValue to be included in the WHERE clause is null.
CurrentValueWHERE clause if
the Null property is "false".
EJBLoadedtrue" if the value gets loaded using ejbLoad().
The new CurrentValue represents the value to be set when inserting or updating a row.
Use this class in the following cases:
Get the saved value from the TransactionCache,
replace it with the loaded value, and set EJBLoaded to "true".
The EJBLoaded value is set to "true" so that a subsequent JDBC update knows it must
flush the EJB cache before it performs an UPDATE operation.
Do this by ensuring your EJB calls super.ejbLoad().
Get the saved value from the TransactionCache
and replace it with the loaded value.
Increment the loaded value and set the EJB attribute value to the incremented value.
The incremented value is saved so that a subsequent JDBC SELECT operation
does not need to read it from the database, and so that a subsequent JDBC UPDATE operation
has the correct value for the WHERE clause.
Do this by ensuring your EJB bean calls super.ejbStore().
SELECT statement is used to obtain the OPTCOUNTER value.
Save the value in the TransactionCache.
This is optional, depending on the application logic, but if it is not done, an intervening change
may not be detected.
Refer to
OPTCOUNTER_COLUMN_NAME,
getSavedOptCounterInfo(Object), and
setCurrentValue(boolean,ResultSet,int).
SELECT ... FOR UPDATE statement is used to obtain the OPTCOUNTER value.
When the OPTCOUNTER value is known, obtained, for example by a previously executed
SELECT statement,
include the OPTCOUNTER value in the WHERE clause
if it is known and has never been incremented or randomized,
and throw an
ECJDBCOptimisticUpdateFailureException if the row is not found.
Refer to getSelectForUpdateSQL(String),
BaseJDBCHelper.getSavedOptCounterInfoForOptimisticSelect(Object),
getWhereClauseFragment(),
setParameter(PreparedStatement,int),
ECJDBCOptimisticUpdateFailureException, and
BaseJDBCHelper.executeOptimisticSelect(PreparedStatement,Object,OptCounterInfo).
DELETE operation is followed by an INSERT operation
in the same transaction.
A DELETE operation followed by an INSERT operation
should appear to another transaction as equivalent to an UPDATE operation.
Before a DELETE statement is executed, determine the current OPTCOUNTER value
and save it in the TransactionCache.
This is optional depending on the application logic.
If there is already a value in the TransactionCache, you can use that value
rather than reading it from the database.
If no subsequent INSERT operation occurs in the same transaction,
it is not necessary to determine and save it.
When a DELETE statement is executed, get the saved value from the TransactionCache and include it
in the WHERE clause
if it is known and has never been incremented or randomized.
If the DELETE statement includes the OPTCOUNTER value in the WHERE clause
and executes successfully but does not delete any rows,
throw an ECJDBCOptimisticUpdateFailureException exception.
Refer to getSelectOptCounterSQL(String,String),
BaseJDBCHelper.getSavedOptCounterInfoForDelete(Object),
getWhereClauseFragment(),
setParameter(PreparedStatement,int),
ECJDBCOptimisticUpdateFailureException, and
BaseJDBCHelper.executeOptimisticDelete(PreparedStatement,Object,OptCounterInfo).
INSERT statement is executed. Get the saved value from the TransactionCache,
increment it, and use it in the INSERT operation.
If there is no saved value, randomly select a value, use it in the INSERT operation,
and save it in the TransactionCache.
By randomly selecting a value, the chance that another transaction does not detect the
change introduced by a DELETE operation followed by an INSERT operation is reduced.
This is only necessary when the application logic performs a DELETE
operation followed by an INSERT operation in the same transaction.
Refer to
getSavedOptCounterInfoForInsert(Object) and
setParameter(PreparedStatement,int).
UPDATE statement is executed. Include the update fragment to increment the
counter, get the saved value from the TransactionCache and include it in the WHERE clause
if it is known and has never been incremented or randomized.
If the update statement includes the OPTCOUNTER value in the WHERE clause
but does not find the specified row,
throw an ECJDBCOptimisticUpdateFailureException exception.
Otherwise, increment the saved value.
Refer to
getIncrementOptCounterFragment(),
BaseJDBCHelper.getSavedOptCounterInfoForUpdate(Object),
getWhereClauseFragment(),
setParameter(PreparedStatement,int),
ECJDBCOptimisticUpdateFailureException, and
BaseJDBCHelper.executeOptimisticUpdate(PreparedStatement,Object,OptCounterInfo).
Note: Some operations are not supported. For example, JDBC cannot be used to update a row after
it has been loaded into an EJB bean and before the bean has been stored.
It is better to avoid mixing EJB beans and JDBC for the same database information.
If necessary, use the BaseJDBCHelper.getSavedOptCounterInfoForUpdate(Object)
method to cause dirty EJB objects to be flushed to the database before executing a JDBC
update operation.
| Modifier and Type | Field and Description |
|---|---|
static java.lang.String |
OPTCOUNTER_COLUMN_NAME
The name of the
OPTCOUNTER column. |
| Modifier and Type | Method and Description |
|---|---|
java.lang.Object |
clone()
Returns a copy of this
OptCounterInfo object. |
static OptCounterInfo |
getAndForgetForNextInsert()
Gets and increments the object most recently set by the setForNextInsert method,
or creates and randomizes a new one created from the default constructor.
|
short |
getCurrentValue()
Get the current
OPTCOUNTER value. |
static java.lang.String |
getDecrementOptCounterFragment()
Returns an SQL fragment that can be used to decrement the current
OPTCOUNTER value. |
static java.lang.String |
getDecrementSQL(java.lang.String astrUpdateFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple UPDATE statement with appropriate phrase to decrement the
OPTCOUNTER column. |
static java.lang.String |
getIncrementOptCounterFragment()
Returns an SQL fragment that can be used to increment the current
OPTCOUNTER value. |
static java.lang.String |
getIncrementSQL(java.lang.String astrUpdateFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple UPDATE statement with appropriate phrase to increment the
OPTCOUNTER column. |
static short |
getNextValue(short aCurrentOptCounterValue)
Gets the next value of the
OPTCOUNTER column (incremented with wrap to 1). |
java.lang.String |
getOptimisticDecrementSQL(java.lang.String astrTableName,
java.lang.String astrWhereClause)
Returns an SQL statement that can be used to decrement the
OPTCOUNTER column of a specific row. |
java.lang.String |
getOptimisticIncrementSQL(java.lang.String astrTableName,
java.lang.String astrWhereClause)
Returns an SQL statement that can be used to increment the
OPTCOUNTER column of a specific row. |
java.lang.String |
getOptimisticSelectForUpdateSQL(java.lang.String astrSelectFragment)
Returns a simple
SELECT statement with the appropriate phrases
to include a previously read opt counter (if any) in the WHERE clause,
and to obtain a FOR UPDATE lock. |
java.lang.String |
getOptimisticSelectForUpdateSQL(java.lang.String astrSelectFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple
SELECT statement with the appropriate phrases
to obtain the opt counter value from the database,
to include a previously read opt counter (if any) in the WHERE clause,
and to obtain a FOR UPDATE lock. |
java.lang.String |
getOptimisticSelectSQL(java.lang.String astrSelectFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple
SELECT statement with the appropriate phrases
to obtain the opt counter and include it in the WHERE clause. |
static OptCounterInfo |
getSavedOptCounterInfo(java.lang.Object aKey)
Gets the
OPTCOUNTER information for a row of a table from the TransactionCache. |
static OptCounterInfo |
getSavedOptCounterInfoForInsert(java.lang.Object aKey)
Gets
OPTCOUNTER information to be used in an INSERT operation. |
static java.lang.String |
getSelectForUpdateFragment()
Returns an SQL fragment that can be used to obtain a
FOR UPDATE lock. |
static java.lang.String |
getSelectForUpdateSQL(java.lang.String astrSelectFragment)
Returns a simple
SELECT statement with an appropriate phrase to
obtain a FOR UPDATE lock. |
static java.lang.String |
getSelectOptCounterSQL(java.lang.String astrTableName,
java.lang.String astrWhereClause)
This method gets an SQL statement that can be used to obtain the current values of the
OPTCOUNTER column. |
static java.lang.String |
getSelectOptCounterSQL(java.lang.String astrTableName,
java.lang.String astrColumnName,
java.lang.String astrWhereClause)
This method gets an SQL statement that can be used to obtain the current values of a specified column
and of the
OPTCOUNTER column. |
java.lang.String |
getUpdateSQL(java.lang.String astrUpdateFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple
UPDATE SQL statement with appropriate optimistic locking phrases. |
java.lang.String |
getUpdateSQL(java.lang.String astrUpdateFragment,
java.lang.String astrWhereClausePrefixFragment,
java.lang.String astrWhereClausePostfixFragment)
Returns a simple
UPDATE SQL statement with appropriate optimistic locking phrases. |
java.lang.String |
getWhereClauseFragment()
Returns either
"" (if the value is not known or has been incremented or randomized),
or
" AND OPTCOUNTER IS NULL" (if the value is null),
or " AND OPTCOUNTER=?" (if the value is not null). |
OptCounterInfo |
increment()
Increment the current value (with wrap to 1).
|
boolean |
isEJBLoaded()
Gets whether the current
OPTCOUNTER value is loaded using ejbLoad(). |
boolean |
isKnown()
Gets whether the current
OPTCOUNTER value is known. |
boolean |
isNull()
Gets whether the current
OPTCOUNTER value is null. |
OptCounterInfo |
randomize()
Sets the current value to a randomly assigned value.
|
OptCounterInfo |
setCurrentValue(boolean abRowExists,
java.sql.ResultSet aResultSet)
Sets the current
OPTCOUNTER information from a ResultSet. |
OptCounterInfo |
setCurrentValue(boolean abRowExists,
java.sql.ResultSet aResultSet,
int aIndex)
Sets the current
OPTCOUNTER information from a ResultSet. |
OptCounterInfo |
setCurrentValue(java.lang.Number anCurrentOptCounterValue)
Sets the current known
OPTCOUNTER value, which may be null. |
OptCounterInfo |
setCurrentValue(short aCurrentOptCounterValue)
Sets the current known, not null,
OPTCOUNTER value. |
OptCounterInfo |
setCurrentValue(java.lang.Short anCurrentOptCounterValue)
Sets the current known
OPTCOUNTER value, which may be null. |
OptCounterInfo |
setEJBLoaded()
Sets the property that indicates that the current
OPTCOUNTER value was loaded using ejbLoad(). |
OptCounterInfo |
setEJBLoaded(boolean abEJBLoaded)
Sets whether the current
OPTCOUNTER value was loaded using ejbLoad(). |
static OptCounterInfo |
setForNextInsert(OptCounterInfo aOptCounterInfo)
Sets an
OptCounterInfo object that will be recalled by the next execution of the
getAndForgetForNextInsert method. |
OptCounterInfo |
setKnown(boolean abKnown)
Sets whether the current
OPTCOUNTER value is known. |
OptCounterInfo |
setNull(boolean abNull)
Sets whether the current known
OPTCOUNTER value is null. |
OptCounterInfo |
setParameter(java.sql.PreparedStatement aPreparedStatement,
int aIndex)
Sets the
OPTCOUNTER value into the specified PreparedStatement
at the specified position, if it is known and not null,
has not been incremented, and has not been randomized. |
java.lang.String |
toString()
Returns a String representation of this object suitable for printing in trace information.
|
public static final java.lang.String OPTCOUNTER_COLUMN_NAME
OPTCOUNTER column.public static java.lang.String getSelectOptCounterSQL(java.lang.String astrTableName,
java.lang.String astrWhereClause)
OPTCOUNTER column.
It retrieves them from the specified table for the rows indicated by the specified WHERE clause.
The WHERE clause should not start with "WHERE".astrTableName - The table nameastrWhereClause - The WHERE clausepublic static java.lang.String getSelectOptCounterSQL(java.lang.String astrTableName,
java.lang.String astrColumnName,
java.lang.String astrWhereClause)
OPTCOUNTER column. It retrieves them from the specified table for the rows
indicated by the specified WHERE clause.
The WHERE clause should not start with "WHERE".
The SQL statement returned is:
"SELECT " + OPTCOUNTER_COLUMN_NAME + ","
+ astrColumnName + ","+ OPTCOUNTER_COLUMN_NAME
+ " FROM " + astrTableName + " WHERE " + astrWhereClauseastrTableName - The table name.astrColumnName - The column name.astrWhereClause - The where clause.public static java.lang.String getSelectForUpdateFragment()
FOR UPDATE lock.
It can be used in an SQL SELECT statement such as:
"SELECT acolumn FROM tablename WHERE conditions"
+ OptCounterInfo.getForUpdateFragment()
Do not call this method during static initialization.
public static java.lang.String getSelectForUpdateSQL(java.lang.String astrSelectFragment)
Returns a simple SELECT statement with an appropriate phrase to
obtain a FOR UPDATE lock.
The string returned is:
astrSelectFragment + getSelectForUpdateFragment()
Do not call this method during static initialization.
astrSelectFragment - the update SQL fragment.public static java.lang.String getIncrementOptCounterFragment()
OPTCOUNTER value.
It can be used in an SQL UPDATE statement such as:
"UPDATE tablename SET "
+ OptCounterInfo.getIncrementOptCounterFragment()
+ " WHERE column2Name=column2Value"Do not call this method during static initialization.
public static java.lang.String getIncrementSQL(java.lang.String astrUpdateFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple UPDATE statement with appropriate phrase to increment the
OPTCOUNTER column.
The string returned is:
astrUpdateFragment + getIncrementOptCounterFragment()
+ astrWhereClauseFragment
Do not call this method during static initialization.
astrUpdateFragment - the update SQL fragment.astrWhereClauseFragment - the WHERE clause fragment.public static java.lang.String getDecrementOptCounterFragment()
OPTCOUNTER value.
It can be used in an SQL "UPDATE" statement such as:
"UPDATE tablename SET "
+ OptCounterInfo.getDecrementOptCounterFragment()
+" WHERE column2Name=column2Value"Do not call this method during static initialization.
public static java.lang.String getDecrementSQL(java.lang.String astrUpdateFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple UPDATE statement with appropriate phrase to decrement the
OPTCOUNTER column.
The string returned is:
astrUpdateFragment + getDecrementOptCounterFragment()
+ astrWhereClauseFragment
Do not call this method during static initialization.
astrUpdateFragment - the update SQL fragment.astrWhereClauseFragment - the WHERE clause fragment.public static short getNextValue(short aCurrentOptCounterValue)
OPTCOUNTER column (incremented with wrap to 1).aCurrentOptCounterValue - the current value to be incremented.OPTCOUNTER column.public static OptCounterInfo getSavedOptCounterInfo(java.lang.Object aKey)
OPTCOUNTER information for a row of a table from the TransactionCache.aKey - uniquely identifies the table and row of the OPTCOUNTER.
For objects with EJB beans, use its primary key object.
For example, for a UserBean, use new MemberKey(member_id)
For JDBC helper classes when there is no corresponding EJB bean, use a unique row identifier.
For example, new SerializableTuple("STOREREL", storeId, relatedStoreId, relationshipTypeName)OPTCOUNTER information for the specified row,
or a new OptCounterInfo constructed from the default constructor
if there was none in the Transaction cache.public static OptCounterInfo getSavedOptCounterInfoForInsert(java.lang.Object aKey)
OPTCOUNTER information to be used in an INSERT operation.
The object returned can be the current saved OptCounterInfo object with its value incremented,
if it is known. Or, it can be a new OptCounterInfo object created with the default constructor, that is
randomly assigned a value.
In either case, the value returned is saved and marked as known.
Do not call this method if there is a possibility that the INSERT
operation will not be performed.aKey - uniquely identifies the table and row of the OPTCOUNTER.
For objects with EJB beans, use its primary key object.
For example, for a UserBean, use new MemberKey(member_id)
For JDBC helper classes when there is no corresponding EJB, use a unique row identifier.
For example, new SerializableTuple("STOREREL", storeId, relatedStoreId, relationshipTypeName)OPTCOUNTER information for the specified row,
to be used in a subsequent insert operation.public static OptCounterInfo setForNextInsert(OptCounterInfo aOptCounterInfo)
OptCounterInfo object that will be recalled by the next execution of the
getAndForgetForNextInsert method.aOptCounterInfo - the object to be set. Can be null.public static OptCounterInfo getAndForgetForNextInsert()
OPTCOUNTER information.public OptCounterInfo setCurrentValue(short aCurrentOptCounterValue)
OPTCOUNTER value.
Side effects: Null is set false, Known is set true.aCurrentOptCounterValue - the value to be set.this.public OptCounterInfo setCurrentValue(java.lang.Short anCurrentOptCounterValue)
OPTCOUNTER value, which may be null.
Side effects: Known is set true.anCurrentOptCounterValue - the value to be set.this.public OptCounterInfo setCurrentValue(java.lang.Number anCurrentOptCounterValue)
OPTCOUNTER value, which may be null.
Side effects: Known is set true.anCurrentOptCounterValue - the value to be set.this.public OptCounterInfo setCurrentValue(boolean abRowExists, java.sql.ResultSet aResultSet) throws java.sql.SQLException
OPTCOUNTER information from a ResultSet.
Known is set to abRowExists.abRowExists - true if aResultSet has been set to the correct row.aResultSet - not used if abRowExists is false.this.java.sql.SQLExceptionpublic OptCounterInfo setCurrentValue(boolean abRowExists, java.sql.ResultSet aResultSet, int aIndex) throws java.sql.SQLException
OPTCOUNTER information from a ResultSet.
Known is set to abRowExists.abRowExists - true if aResultSet has been set to the correct row.aResultSet - not used if abRowExists is false.aIndex - the index of the OPTCOUNTER column in the result set.
Not used if abRowExists is false.this.java.sql.SQLExceptionpublic OptCounterInfo setNull(boolean abNull)
OPTCOUNTER value is null.
Side effect: Known is set true.abNull - true if the value is null.this.public OptCounterInfo setKnown(boolean abKnown)
OPTCOUNTER value is known.abKnown - true if the value is known.this.public OptCounterInfo setEJBLoaded(boolean abEJBLoaded)
OPTCOUNTER value was loaded using ejbLoad().abEJBLoaded - true if the value was loaded using ejbLoad().this.public OptCounterInfo setEJBLoaded()
OPTCOUNTER value was loaded using ejbLoad().this.public short getCurrentValue()
OPTCOUNTER value.OPTCOUNTER value.public OptCounterInfo increment()
Increment the current value (with wrap to 1).
Side effect: Null is set false.
Side effect: The WHERE clause fragment for an incremented OPTCOUNTER is always empty,
since incrementing the value implies that the row has been updated. This means that
a write lock has been obtained,
hence no other transaction can modify the row until this transaction commits,
and so the WHERE clause fragment that detects changes is not required.
this.public OptCounterInfo randomize()
Sets the current value to a randomly assigned value.
Side effect: Null is set false.
Side effect: The WHERE clause fragment for a randomized OPTCOUNTER is always empty,
since randomizing the value implies that the row has been created.
This means that a write lock has been obtained,
hence no other transaction can modify the row until this transaction commits,
and so the WHERE clause fragment that detects changes is not required.
this.public boolean isNull()
OPTCOUNTER value is null.true if the current OPTCOUNTER value is null.public boolean isKnown()
OPTCOUNTER value is known.true if the current OPTCOUNTER value is known.public boolean isEJBLoaded()
OPTCOUNTER value is loaded using ejbLoad().true if the current OPTCOUNTER value is loaded using ejbLoad().public java.lang.Object clone()
throws java.lang.CloneNotSupportedException
OptCounterInfo object.clone in class java.lang.ObjectOptCounterInfo object.java.lang.CloneNotSupportedExceptionpublic java.lang.String toString()
toString in class java.lang.Objectpublic java.lang.String getWhereClauseFragment()
"" (if the value is not known or has been incremented or randomized),
or
" AND OPTCOUNTER IS NULL" (if the value is null),
or " AND OPTCOUNTER=?" (if the value is not null).WHERE clause fragment.public java.lang.String getUpdateSQL(java.lang.String astrUpdateFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple UPDATE SQL statement with appropriate optimistic locking phrases.
The string returned is:
astrUpdateFragment + "," + getIncrementOptCounterFragment()
+ " " + astrWhereClauseFragment + getWhereClauseFragment()
Do not call this method during static initialization.
astrUpdateFragment - the UPDATE SQL fragment.astrWhereClauseFragment - the WHERE clause fragment.public java.lang.String getUpdateSQL(java.lang.String astrUpdateFragment,
java.lang.String astrWhereClausePrefixFragment,
java.lang.String astrWhereClausePostfixFragment)
Returns a simple UPDATE SQL statement with appropriate optimistic locking phrases.
The string returned is:
astrUpdateFragment + "," + getIncrementOptCounterFragment()
+ " " + astrWhereClausePrefixFragment + getWhereClauseFragment()
+ astrWhereClausePostfixFragment
Do not call this method during static initialization.
astrUpdateFragment - the UPDATE SQL fragment.astrWhereClausePrefixFragment - the WHERE clause prefix fragment.astrWhereClausePostfixFragment - the WHERE clause postfix fragment.public java.lang.String getOptimisticSelectSQL(java.lang.String astrSelectFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple SELECT statement with the appropriate phrases
to obtain the opt counter and include it in the WHERE clause.
The string returned is:
astrSelectFragment
+ "," + OPTCOUNTER_COLUMN_NAME
+ " " + astrWhereClauseFragment + getWhereClauseFragment()
Do not call this method during static initialization.
astrSelectFragment - the select SQL fragment.astrWhereClauseFragment - the WHERE clause fragment.public java.lang.String getOptimisticIncrementSQL(java.lang.String astrTableName,
java.lang.String astrWhereClause)
Returns an SQL statement that can be used to increment the OPTCOUNTER column of a specific row.
astrTableName - the table name.astrWhereClause - a WHERE clause (should NOT start with "WHERE")
that uniquely identifies the row.public java.lang.String getOptimisticDecrementSQL(java.lang.String astrTableName,
java.lang.String astrWhereClause)
Returns an SQL statement that can be used to decrement the OPTCOUNTER column of a specific row.
astrTableName - the table name.astrWhereClause - a WHERE clause (should NOT start with "WHERE")
that uniquely identifies the row.public java.lang.String getOptimisticSelectForUpdateSQL(java.lang.String astrSelectFragment,
java.lang.String astrWhereClauseFragment)
Returns a simple SELECT statement with the appropriate phrases
to obtain the opt counter value from the database,
to include a previously read opt counter (if any) in the WHERE clause,
and to obtain a FOR UPDATE lock.
The string returned is:
astrSelectFragment
+ "," + OPTCOUNTER_COLUMN_NAME
+ " " + astrWhereClauseFragment + getWhereClauseFragment()
+ getSelectForUpdateFragment()
Do not call this method during static initialization.
astrSelectFragment - the select SQL fragment.astrWhereClauseFragment - the WHERE clause fragment.public java.lang.String getOptimisticSelectForUpdateSQL(java.lang.String astrSelectFragment)
Returns a simple SELECT statement with the appropriate phrases
to include a previously read opt counter (if any) in the WHERE clause,
and to obtain a FOR UPDATE lock.
The string returned is:
astrSelectFragment + getWhereClauseFragment()
+ getSelectForUpdateFragment()
Do not call this method during static initialization.
astrSelectFragment - the select SQL fragment.public OptCounterInfo setParameter(java.sql.PreparedStatement aPreparedStatement, int aIndex) throws java.sql.SQLException
OPTCOUNTER value into the specified PreparedStatement
at the specified position, if it is known and not null,
has not been incremented, and has not been randomized.aPreparedStatement - the PreparedStatement.aIndex - the position of the parameter to be set in the PreparedStatement.java.sql.SQLException