Class SRecordInstance
- java.lang.Object
-
- simpleorm.dataset.SRecordInstance
-
- All Implemented Interfaces:
java.io.Serializable
- Direct Known Subclasses:
PersistentRecord
public abstract class SRecordInstance extends java.lang.Object implements java.io.Serializable
Each SRecordInstance represents an individual record in memory that either correspond to a row in the database or a new record that has yet to be inserted.RecordInstances are normally created by either
findOrCreate
orSSessionJdbc#Query
. The former selects a specific record by primary key, while the latter retrieves all records that satify a query. Instances may also be directly created by without reference to a session.The main methods are
get*
andset*
which get and set field values of the record.deleteRecord()
deletes a row.No two RecordInstances can have the same primary key field values within the same connection. Attempts to retrieve the same row twice will simple return a pointer to an existing SRecordInstance. There is no relationship between RecordInstances in different connections -- all locking is done by the underlying database.
- See Also:
- Serialized Form
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
SRecordInstance.BrokenOptimisticLockException
Exception thrown due to broken optimistic locks.
-
Constructor Summary
Constructors Modifier Constructor Description protected
SRecordInstance()
Protected default constructor.
-
Method Summary
All Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description java.lang.String
allFields()
For debugging like toString(), but shows all the fields.void
assertNewRow()
Throws an excpetion if !isNewRow()
.void
assertNotNewRow()
void
defineInitialValue(SFieldMeta field)
Defines the current value of the field to be the initial value, which is then used for optimistic locks etc.void
deleteRecord()
Sets a flag to delete this record when the transaction is commited.void
doQueryRecord()
void
doValidateRecord()
boolean
equals(java.lang.Object key2)
Determines whehter two SRecordInstances are for the same SRecordMeta and have the same primary key fields.<T extends SRecordInstance>
TfindReference(SFieldReference<T> field)
<T extends SRecordInstance>
TfindReference(SFieldReference<T> field, SQueryMode queryMode)
<T extends SRecordInstance>
TfindReference(SFieldReference<T> field, SQueryMode queryMode, SSelectMode selectMode)
Gets a record referenced bythis.field
.<T extends SRecordInstance>
TfindReference(SFieldReference<T> field, SSelectMode selectMode)
java.math.BigDecimal
getBigDecimal(SFieldMeta field)
etc.boolean
getBoolean(SFieldMeta field)
Returns false if null.byte[]
getBytes(SFieldMeta field)
Casts getObject() to byte[].SDataSet
getDataSet()
java.sql.Date
getDate(SFieldMeta field)
etc.double
getDouble(SFieldMeta field)
Casts getObject() to double iff a Number, see getString().<T extends java.lang.Enum<T>>
TgetEnum(SFieldEnum<T> field)
java.lang.Object
getInitialValue(SFieldMeta fieldMeta)
The value that was read from (or flushed to) the database.int
getInt(SFieldMeta field)
Casts getObject() to int iff a Number, see getString().SLog
getLogger()
long
getLong(SFieldMeta field)
Casts getObject() to long iff a Number, see getString().abstract SRecordMeta<?>
getMeta()
This must be defined in every user record's definition to access the SRecord which provides the meta data for this instance.java.lang.Object
getObject(SFieldMeta field)
Returns the field's value as a Java Object in the type stored in the dataset.java.lang.Object
getRawArrayValue(SFieldMeta fmeta)
Raw accessor for field value.java.lang.Object
getReferenceNoQuery(SFieldReference field)
Get a reference, but do not query either the dataset or the database.java.lang.String
getString(SFieldMeta field)
Gets the value of field cast to a String, trimed of trailing spaces.java.sql.Time
getTime(SFieldMeta field)
etc.java.sql.Timestamp
getTimestamp(SFieldMeta field)
etc.int
hashCode()
Seeequals()
.boolean
isAttached()
True if this instance is attached to the current begun transaction.boolean
isDeleted()
boolean
isDirty()
True iff this record is dirty but not yet flushed to the database.boolean
isDirty(SFieldMeta field)
Tests whether just field is dirty.boolean
isEmpty(SFieldMeta field)
True if field is the empty value, ie.boolean
isNewRow()
Often called after {SRecordMeta#findOrCreate} to determine whether a row was retrieved from the database (not a new row) or whether this record represents a new row that will be inserted when it is flushed.boolean
isNotDestroyed()
True if the record has valid data, ie.boolean
isNull(SFieldMeta field)
Was the field SQL NULL in the database? (eg.boolean
isReadOnly()
boolean
isValid(SFieldMeta field)
True if the field has been queried as part of the current transaction and so a get is valid.protected void
onQueryRecord()
Override this to get field values just after a record is actually retrieved, by findOrCreate or query.protected void
onValidateField(SFieldMeta field, java.lang.Object newValue)
Called after individual field validators each time a field's value is set, (now) including keys.protected void
onValidateRecord()
Override this to validate records before flush.void
setBigDecimal(SFieldMeta field, java.math.BigDecimal value)
void
setBoolean(SFieldMeta field, boolean value)
void
setBytes(SFieldMeta field, byte[] value)
void
setDate(SFieldMeta field, java.util.Date value)
SeesetTimestamp(simpleorm.dataset.SFieldMeta, java.util.Date)
for discussion of Date parameter.void
setDirty(boolean val)
Sets this record to be dirty so that it will be updated in the database.void
setDouble(SFieldMeta field, double value)
void
setEmpty(SFieldMeta field)
Sets field to be empty, ie.<T extends java.lang.Enum<T>>
voidsetEnum(SFieldEnum<T> field, java.lang.Enum<T> value)
void
setInt(SFieldMeta field, int value)
void
setLong(SFieldMeta field, long value)
void
setNewRow(boolean val)
void
setNull(SFieldMeta field)
void
setObject(SFieldMeta field, java.lang.Object value)
Generic routine to set a fields value.void
setObject(SFieldMeta field, java.lang.Object value, boolean fieldValidate)
Enables value to be set with field validation suppressed, rarely used.void
setRawArrayValue(SFieldMeta fmeta, java.lang.Object value)
Raw setter for field value.void
setReadOnly(boolean val)
void
setReference(SFieldReference<?> field, SRecordInstance value)
void
setString(SFieldMeta field, java.lang.String value)
Sets the value of the field from a string, casting if necessary.void
setTime(SFieldMeta field, java.util.Date value)
SeesetTimestamp(simpleorm.dataset.SFieldMeta, java.util.Date)
for discussion of Date parameter.void
setTimestamp(SFieldMeta field, java.util.Date value)
Note that value should normally be a java.sql.Timestamp (a subclass of java.util.Date).java.lang.String
toString()
toString just shows the Key field(s).void
validatePrimaryKeys()
boolean
wasInCache()
Was in the cache before the most recent findOrCreate.
-
-
-
Method Detail
-
getMeta
public abstract SRecordMeta<?> getMeta()
This must be defined in every user record's definition to access the SRecord which provides the meta data for this instance. It is normally defined as:-SRecord getMeta() { return meta; };
The actual
meta
variable is thus not Serialized, but it would not be anyway as it is usually static.
-
equals
public boolean equals(java.lang.Object key2)
Determines whehter two SRecordInstances are for the same SRecordMeta and have the same primary key fields.This is purely for the purpose of putting
SRecordInstances
in theSSession.transactionCache
. This is done astc.put(SRecordInstance, SRecordInstance)
, ie the instance is used for both the key and the body. This avoids having to create a separate primary key object for each record instance.It only foreign keys, not referenced SRecordInstances which may be null if the parent record has not been retrieved.
- Overrides:
equals
in classjava.lang.Object
-
hashCode
public int hashCode()
Seeequals()
.- Overrides:
hashCode
in classjava.lang.Object
-
getObject
public java.lang.Object getObject(SFieldMeta field)
Returns the field's value as a Java Object in the type stored in the dataset.Methods such as
getString()
dispach to this method but are generally more convenient because the cast the result to the correct type. This method in turn just dispaches tofield.getFieldValue()
, ie. it is the declaredtype of the SField that determines how the value is retrieved.Also lazily fetches referenced records if field is a reference. But findReference normally used instead. Don't rely on null result, as it could mean field is null, or it has not been queried or set. Use isNull(field) instead.
Enums are now stored as enums.
-
setObject
public void setObject(SFieldMeta field, java.lang.Object value)
Generic routine to set a fields value. Just dispaches tofield.setFieldValue(convertToField(value))
-
setObject
public void setObject(SFieldMeta field, java.lang.Object value, boolean fieldValidate)
Enables value to be set with field validation suppressed, rarely used.
-
isNull
public boolean isNull(SFieldMeta field)
Was the field SQL NULL in the database? (eg. getInt would return 0 for this case.) Does not need to do query for reference fields, just checks if any refing scalars are null.
-
setNull
public void setNull(SFieldMeta field)
-
isEmpty
public boolean isEmpty(SFieldMeta field)
True if field is the empty value, ie. null or "" or spaces.- See Also:
SFieldFlags.SMANDATORY
-
setEmpty
public void setEmpty(SFieldMeta field)
Sets field to be empty, ie. currentlysetObject(, null)
. But other options will be added later.- See Also:
SFieldFlags.SMANDATORY
-
getString
public java.lang.String getString(SFieldMeta field)
Gets the value of field cast to a String, trimed of trailing spaces. This is equivalent togetObject().toString().trimTrailingSpaces()
. So the field type itself need not beSFieldString
, but just something that can be cast to a String. Trailing spaces can be a problem with some databases and fileds declaredCHAR
.Note that if you do not want trailing spaces trimmed, then just call getObject().toString() manually. (For CHAR fields, most dbs/jdbc drivers seem to trim, but this is highly inconsistent.)
## Trimming is an issue with CHAR style fields that pad with spaces. Currently we always read from database into the fields without trimming. The idea being to let the SimpleORM user get at the raw query result using getObject, whatever that raw result is.
Most DBs seem to trim for us. But some may not, and some may require the trailing spaces on queries. Certainly trailing spaces in the objects will upset the record cache, and there is some dubious code in SRecordFinder.retrieveRecord() to handle this.
I think that for CHAR fields we need to always trim at database read, and pad where needed. This should also be dispatched to DB handler. I think that Oracle gives grief. (Note that trim means trailing spaces, leading should be left alone.)
I have not done this because it would require testing on many datbases.
-
setString
public void setString(SFieldMeta field, java.lang.String value)
Sets the value of the field from a string, casting if necessary. So this can be used to set an Integer field, say.
-
getInt
public int getInt(SFieldMeta field)
Casts getObject() to int iff a Number, see getString(). Returns 0 if null, following JDBC.
-
setInt
public void setInt(SFieldMeta field, int value)
-
getLong
public long getLong(SFieldMeta field)
Casts getObject() to long iff a Number, see getString(). Returns 0 if null, following JDBC. Note that longs may not be accurately supported by the database -- see SFieldLong.
-
setLong
public void setLong(SFieldMeta field, long value)
-
getDouble
public double getDouble(SFieldMeta field)
Casts getObject() to double iff a Number, see getString(). Returns 0 if null, following JDBC.
-
setDouble
public void setDouble(SFieldMeta field, double value)
-
getBoolean
public boolean getBoolean(SFieldMeta field)
Returns false if null.
-
setBoolean
public void setBoolean(SFieldMeta field, boolean value)
-
getTimestamp
public java.sql.Timestamp getTimestamp(SFieldMeta field)
etc. for Timestamp.
-
setTimestamp
public void setTimestamp(SFieldMeta field, java.util.Date value)
Note that value should normally be a java.sql.Timestamp (a subclass of java.util.Date). However, if it is a java.util.Date instead, then it will replaced by a new java.sql.Timestamp object before being set. This is convenient for people using java.util.Date as their main date type.
-
getDate
public java.sql.Date getDate(SFieldMeta field)
etc. for Date. ### Should convert strings to Date, ISO etc. Likewise other types. (Painful to do in Java!)
-
setDate
public void setDate(SFieldMeta field, java.util.Date value)
SeesetTimestamp(simpleorm.dataset.SFieldMeta, java.util.Date)
for discussion of Date parameter.
-
getTime
public java.sql.Time getTime(SFieldMeta field)
etc. for Time.
-
setTime
public void setTime(SFieldMeta field, java.util.Date value)
SeesetTimestamp(simpleorm.dataset.SFieldMeta, java.util.Date)
for discussion of Date parameter.
-
getBigDecimal
public java.math.BigDecimal getBigDecimal(SFieldMeta field)
etc. for BigDecimal.
-
setBigDecimal
public void setBigDecimal(SFieldMeta field, java.math.BigDecimal value)
-
getEnum
public <T extends java.lang.Enum<T>> T getEnum(SFieldEnum<T> field)
-
setEnum
public <T extends java.lang.Enum<T>> void setEnum(SFieldEnum<T> field, java.lang.Enum<T> value)
-
getBytes
public byte[] getBytes(SFieldMeta field)
Casts getObject() to byte[].
-
setBytes
public void setBytes(SFieldMeta field, byte[] value)
-
findReference
public <T extends SRecordInstance> T findReference(SFieldReference<T> field, SQueryMode queryMode, SSelectMode selectMode)
Gets a record referenced bythis.field
. Does a lazy lookup on the SDataSet.getSession() if necessary, and if attached to a session.If the field is null but all the primary key fields are non null then does a
dataset.find()
and if necessary aSSessionI.findOrCreate()
to provide a referenced record.
-
findReference
public <T extends SRecordInstance> T findReference(SFieldReference<T> field, SSelectMode selectMode)
-
findReference
public <T extends SRecordInstance> T findReference(SFieldReference<T> field, SQueryMode queryMode)
-
findReference
public <T extends SRecordInstance> T findReference(SFieldReference<T> field)
-
setReference
public void setReference(SFieldReference<?> field, SRecordInstance value)
-
getReferenceNoQuery
public java.lang.Object getReferenceNoQuery(SFieldReference field)
Get a reference, but do not query either the dataset or the database. Returns null if a corresponding scalar field is null. Returns Boolean.FALSE if it is not null, but has not been queried from the database.
-
setDirty
public void setDirty(boolean val)
Sets this record to be dirty so that it will be updated in the database. Normally done implicitly by setting a specific column.NOP - But may occasionally be useful after a findOrInsert() to add a record that contains nothing appart from its primary key. ===> isNewRow is here for that
-
isDirty
public boolean isDirty()
True iff this record is dirty but not yet flushed to the database. May be both dirty and unattached.A record is not dirty if a record has been flushed to the database but the transaction not committed.
## Should add wasEverDirty method for both record and fields for validation tests.
-
isDirty
public boolean isDirty(SFieldMeta field)
Tests whether just field is dirty.
-
wasInCache
public boolean wasInCache()
Was in the cache before the most recent findOrCreate. (Will always been in the cache after a findOrCreate.) Used to prevent two create()s for the same key. Also for unit tests.
-
deleteRecord
public void deleteRecord()
Sets a flag to delete this record when the transaction is commited. The record is not removed from the transaction cache. Any futurefindOrCreate
will thus return the deleted record but its fields may not be referenced. (isDeleted
can be used to determine that the record has been deleted.)The record is only deleted from the database when the transaction is committed or is flushed. Thus a transaction that nulls out references to a parent record and then deletes the parent record will not cause a referential integrity violation because the update order is preserved so that the updates will (normally) be performed before the deletes.
Note that for Optimistic locks only those fields that were retrieved are checked for locks.
-
isDeleted
public boolean isDeleted()
-
isNewRow
public boolean isNewRow()
Often called after {SRecordMeta#findOrCreate} to determine whether a row was retrieved from the database (not a new row) or whether this record represents a new row that will be inserted when it is flushed.
-
setNewRow
public void setNewRow(boolean val)
-
assertNewRow
public void assertNewRow()
Throws an excpetion if !isNewRow()
. Handy, use often in your code to trap nasty errors.
-
assertNotNewRow
public void assertNotNewRow()
- See Also:
assertNewRow()
-
isNotDestroyed
public boolean isNotDestroyed()
True if the record has valid data, ie. it has not been destroyed. (This has nothing to do with validateRecord.)
-
isValid
public boolean isValid(SFieldMeta field)
True if the field has been queried as part of the current transaction and so a get is valid. Use this to guard validations if partial column queries are performed. See isDirty.
-
isAttached
public boolean isAttached()
True if this instance is attached to the current begun transaction. Exception if is attached but not to the current transaction or the current transaction has not begun. #### not right.
-
toString
public java.lang.String toString()
toString just shows the Key field(s). It is meant to be consise, often used as part of longer messages.- Overrides:
toString
in classjava.lang.Object
-
allFields
public java.lang.String allFields()
For debugging like toString(), but shows all the fields.
-
onValidateField
protected void onValidateField(SFieldMeta field, java.lang.Object newValue)
Called after individual field validators each time a field's value is set, (now) including keys. Not called as values are retrieved from database.Throw an SException.Validation if not OK. The value is not assigned, and the transaction can continue. The exception will be augmented with
This is called after the value has been converted to its proper type, eg. from a String to a Double and the field value has been updated.
If the validation fails, the field is automatically set back to its oldValue.
This is called for key values as well. This is only for newly created records but is during the findOrCreate -- ie it is called even if the record is never made dirty and thus saved.
-
doValidateRecord
public void doValidateRecord()
-
onValidateRecord
protected void onValidateRecord()
Override this to validate records before flush. Throw an SValidationException if not OK.This is called just before a record would be flushed. Only dirty records are validated. If the validation fails then the record is not flushed. (It may also be called directly by the application to validate the record before it is flushed.)
Use this routine when a record may be in a temporarily invalid state, but which must be corrected before flushing. This is common when there is a more complex relationship between different fields that cannot be validated until all the fields have been assigned values.
-
onQueryRecord
protected void onQueryRecord()
Override this to get field values just after a record is actually retrieved, by findOrCreate or query.
-
doQueryRecord
public void doQueryRecord()
-
validatePrimaryKeys
public void validatePrimaryKeys()
-
setRawArrayValue
public void setRawArrayValue(SFieldMeta fmeta, java.lang.Object value)
Raw setter for field value. Internal to Simpleorm. Assigns directly into the array of values. No validation or conversion.- Parameters:
fmeta
- the field to setvalue
- the new value of the field, as is, can be null
-
getRawArrayValue
public java.lang.Object getRawArrayValue(SFieldMeta fmeta)
Raw accessor for field value. Internal to Simpleorm. Gets directly from the array of values. No findReference. No Valid test.- Parameters:
fmeta
- the field to get
-
getInitialValue
public java.lang.Object getInitialValue(SFieldMeta fieldMeta)
The value that was read from (or flushed to) the database. Used for optimistic locking, and also just to tell how fields change.
-
defineInitialValue
public void defineInitialValue(SFieldMeta field)
Defines the current value of the field to be the initial value, which is then used for optimistic locks etc. Called just after a record is read or updated.
-
getLogger
public SLog getLogger()
-
isReadOnly
public boolean isReadOnly()
-
setReadOnly
public void setReadOnly(boolean val)
-
getDataSet
public SDataSet getDataSet()
-
-