com.scooterframework.orm.activerecord
Class ActiveRecord

java.lang.Object
  extended by com.scooterframework.orm.activerecord.ActiveRecordClass
      extended by com.scooterframework.orm.activerecord.ActiveRecord
All Implemented Interfaces:
RESTified, java.io.Serializable
Direct Known Subclasses:
Tag, Tagging

public class ActiveRecord
extends ActiveRecordClass
implements RESTified, java.io.Serializable

ActiveRecord represents a dynamic record in a particular database. Column meta data of the table are retrieved before the ActiveRecord instance is created. The following is an example for posts table.

 public class Post extends ActiveRecord {
 }
 

If not specified, the table name an ActiveRecord class maps to is the plural form of the class name. And the database is the default database connection defined in the database.properties file.

Subclass should override the getTableName() method or the getConnectionName() method if non-default behavior is required. For example, the follow code defines a Post class that links with all_posts table in the blog_test database.

 public class Post extends ActiveRecord {
     public String getTableName() {
         return "all_posts";
     }
     
     public String getConnectionName() {
         return "blog_test";
     }
 }
 

To establish relations with other models, all subclasses must implement the registerRelations() method by calling proper relationship setup methods: hasOne, belongsTo, hasMany, hasManyThrough, etc. For example:

 public class Post extends ActiveRecord {
     public void registerRelations() {
         hasMany("comments");
     }
 }
 

To modify an attribute of a record, you need to use one of the setData methods. Otherwise, the change may not be saved.

Specifying conditions

Conditions are often supplied in find, update and delete related methods. They help to construct WHERE clause of a SQL statement. Conditions can be provided in three ways:

  1. conditionsSQL String
  2. conditionsSQL String and conditionsSQLData Array
  3. conditionsSQL String and conditionsSQLData Map

conditionsSQL String specifies a SQL fragment which is used in where clause. For example:

 conditionsSQL: "id in (1, 3, 5, 7) and content like '%Java%'"
 

conditionsSQL String and conditionsSQLData Array allows dynamic data in a SQL fragment. Each element in the array is corresponding to the value to be set to the conditionsSQL. Internally, the array is converted to a map with key starting from 1 for each element in the array. For example:

 conditionsSQL: "first_name=? OR last_name=?"
 conditionsSQLData array: {"John", "Doe"}
 

conditionsSQL String and conditionsSQLData Map allows dynamic data in a SQL fragment. For example:

 conditionsSQL: "first_name=?1 OR last_name=?2"
 conditionsSQLData map: 1=John, 2=Doe
 

Querying APIs

The following chainable methods are introduced for retrieving data from the database.

Each method above allows us to retrieve data in a chainable way. For example, in a PetClinic application:

 To retrieve a pet named Leo:
 ActiveRecord Leo = Pet.where("name='Leo'").getRecord();

 The SQL equivalent of the above is:
 SELECT * FROM pets WHERE name = 'Leo'

 To retrieve all pets owned by owners with id 6 and 10, order by latest birth date:
 List pets = Pet.where("owner_id IN (6, 10)").orderBy("birth_date DESC").getRecords();

 The SQL equivalent of the above is:
 SELECT * FROM pets WHERE owner_id IN (6, 10) ORDER BY birth_date DESC

 To retrieve a pet owner along with all the pets he/she has and each pet's type in one query (eager loading):
 ActiveRecord owner6 = Owner.where("owners.id=6").includes("pets=>visits, pets=>type").getRecord();

 The SQL equivalent of the above is:
 SELECT OWNERS.ID AS OWNERS_ID, OWNERS.FIRST_NAME AS OWNERS_FIRST_NAME,
 OWNERS.LAST_NAME AS OWNERS_LAST_NAME, OWNERS.ADDRESS AS OWNERS_ADDRESS,
 OWNERS.CITY AS OWNERS_CITY, OWNERS.TELEPHONE AS OWNERS_TELEPHONE,
 PETS.ID AS PETS_ID, PETS.NAME AS PETS_NAME, PETS.BIRTH_DATE AS PETS_BIRTH_DATE,
 PETS.TYPE_ID AS PETS_TYPE_ID, PETS.OWNER_ID AS PETS_OWNER_ID,
 VISITS.ID AS VISITS_ID, VISITS.PET_ID AS VISITS_PET_ID,
 VISITS.VISIT_DATE AS VISITS_VISIT_DATE, VISITS.DESCRIPTION AS VISITS_DESCRIPTION,
 OWNERS_PETS.ID AS OWNERS_PETS_ID, OWNERS_PETS.NAME AS OWNERS_PETS_NAME,
 OWNERS_PETS.BIRTH_DATE AS OWNERS_PETS_BIRTH_DATE,
 OWNERS_PETS.TYPE_ID AS OWNERS_PETS_TYPE_ID,
 OWNERS_PETS.OWNER_ID AS OWNERS_PETS_OWNER_ID,
 TYPES.ID AS TYPES_ID, TYPES.NAME AS TYPES_NAME
 FROM OWNERS LEFT OUTER JOIN PETS ON OWNERS.ID=PETS.OWNER_ID
             LEFT OUTER JOIN VISITS ON PETS.ID=VISITS.PET_ID
             LEFT OUTER JOIN PETS OWNERS_PETS ON OWNERS.ID=OWNERS_PETS.OWNER_ID
             LEFT OUTER JOIN TYPES ON OWNERS_PETS.TYPE_ID=TYPES.ID
 WHERE OWNERS.ID = 6
 

Specifying options (properties)

Please notice that in all finder methods, options are replaced by chainable querying methods described above. options are used in specifying relations.

options can be either a string or a map.

In an option string, each name-value pair is separated by ';' character, while within each name-value pair, name and value strings are separated by ':' character. For example, an option string like the following:

 conditions_sql: id in (1, 2, 3); include: category, user;
 order_by: first_name, salary DESC; cascade: delete
 
is equivalent to a HashMap with the following entries:
 key                 value
 --------------      -----
 conditions_sql  =>  id in (1, 2, 3)
 include         =>  category, user
 order_by        =>  first_name, salary desc
 cascade         =>  delete
 

Options string or map are used in association methods such as hasMany and hasManyThrough. The following is a list of allowed properties: model, mapping, finder_sql, conditions_sql, include, join_type, order_by, unique, cascade. Please note that model property is only used in setting up relations.

Dynamic finders

Dynamic finders simulate Ruby-on-Rails's finder methods. These methods are findAllBy, findFirstBy, and findLastBy. The first input parameter of these methods is columns which is a string of column names linked by _and_, such as:

     {columnName}_and_{columnName}_and_...
 

A client can call this method as follows:

     Employee.findAllBy("firstName_and_lastName_and_age", {"John", "Doe", Integer.valueOf(29)});
     Employee.findAllBy("city", {"LA"});
 

Validators

See java doc of Validators class.

See Also:
Serialized Form

Constructor Summary
ActiveRecord()
          Constructs an instance of ActiveRecord.
ActiveRecord(java.lang.String tableName)
          Constructs an instance of ActiveRecord.
ActiveRecord(java.lang.String connectionName, java.lang.String tableName)
          Constructs an instance of ActiveRecord for a specific database connection.
 
Method Summary
 void actAsInCategory(java.lang.String category, java.lang.Class<? extends ActiveRecord> target)
          Acts as a certain type in a category.
 void actAsInCategory(java.lang.String type, java.lang.String category, java.lang.Class<? extends ActiveRecord> target)
          Acts as a certain type in a category.
 void actAsInCategory(java.lang.String type, java.lang.String category, java.lang.String relationType, java.lang.Class<? extends ActiveRecord> target, java.lang.String bcProperties, java.lang.String cbProperties)
          Acts as a certain type in a category.
protected  void afterCreate()
          Do something after the record is created in database.
protected  void afterDelete()
          Do something after the record is deleted in database.
protected  void afterFind()
          Do something after the record is found in database.
protected  void afterSave()
          Do something after the record is saved in database.
protected  void afterSetData(int columnIndex)
          Records the column index that is modified and sets dirty flag
protected  void afterSetData(java.util.List<java.lang.String> modifiedColumnNames)
          Records those columns that are modified and sets dirty flag.
protected  void afterSetData(java.lang.String columnName)
          Records the column that is modified and sets dirty flag
protected  void afterUpdate()
          Do something after the record is updated in database.
 AssociatedRecords allAssociated(java.lang.Class<? extends ActiveRecord> target)
          Returns an AssociatedRecords instance of a specific class type.
 AssociatedRecords allAssociated(java.lang.Class<? extends ActiveRecord> target, boolean refresh)
          Returns an AssociatedRecords instance of a specific class type.
 AssociatedRecords allAssociated(java.lang.Class<? extends ActiveRecord> target, java.lang.String options)
          Returns an AssociatedRecords instance of a specific class type.
 AssociatedRecords allAssociated(java.lang.Class<? extends ActiveRecord> target, java.lang.String options, boolean refresh)
          Returns an AssociatedRecords instance of a specific class type.
 AssociatedRecords allAssociated(java.lang.String associationId)
          Returns an AssociatedRecords instance.
 AssociatedRecords allAssociated(java.lang.String associationId, boolean refresh)
          Returns an AssociatedRecords instance.
 AssociatedRecords allAssociated(java.lang.String associationId, java.lang.String options)
          Returns an AssociatedRecords instance.
 AssociatedRecords allAssociated(java.lang.String associationId, java.lang.String options, boolean refresh)
          Returns an AssociatedRecords instance.
 AssociatedRecordsInCategory allAssociatedInCategory(java.lang.String category)
          Returns an AssociatedRecordsInCategory instance.
 AssociatedRecordsInCategory allAssociatedInCategory(java.lang.String category, boolean refresh)
          Returns an AssociatedRecordsInCategory instance.
 AssociatedRecordsInCategory allAssociatedInCategory(java.lang.String category, java.lang.String type)
          Returns an AssociatedRecordsInCategory instance.
 AssociatedRecordsInCategory allAssociatedInCategory(java.lang.String category, java.lang.String type, boolean refresh)
          Returns an AssociatedRecordsInCategory instance.
 AssociatedRecord associated(java.lang.Class<? extends ActiveRecord> target)
          Returns an AssociatedRecord instance of a specific class type.
 AssociatedRecord associated(java.lang.Class<? extends ActiveRecord> target, boolean refresh)
          Returns an AssociatedRecord instance of a specific class type.
 AssociatedRecord associated(java.lang.Class<? extends ActiveRecord> target, java.lang.String options)
          Returns an AssociatedRecord instance of a specific class type.
 AssociatedRecord associated(java.lang.Class<? extends ActiveRecord> target, java.lang.String options, boolean refresh)
          Returns an AssociatedRecord instance of a specific class type.
 AssociatedRecord associated(java.lang.String associationId)
          Returns an AssociatedRecord instance.
 AssociatedRecord associated(java.lang.String associationId, boolean refresh)
          Returns an AssociatedRecord instance.
 AssociatedRecord associated(java.lang.String associationId, java.lang.String options)
          Returns an AssociatedRecord instance.
 AssociatedRecord associated(java.lang.String associationId, java.lang.String options, boolean refresh)
          Returns an AssociatedRecord instance.
 AssociatedRecord associatedInCategory(java.lang.String category)
          Returns associated record of this join model based on the type value of the type field.
 AssociatedRecord associatedInCategory(java.lang.String category, boolean refresh)
          Returns associated record of this join model based on the type value of the type field.
protected  void beforeCreate()
          Do something before the record is created in database.
protected  void beforeDelete()
          Do something before the record is deleted in database.
protected  void beforeFind()
          Do something before the record is found in database.
protected  void beforeSave()
          Do something before the record is saved in database.
protected  void beforeSetData()
          Creates a backup copy of the current record data
protected  void beforeUpdate()
          Do something before the record is updated in database.
 void belongsTo(java.lang.Class<? extends ActiveRecord> target)
          Sets belongs-to relation.
 void belongsTo(java.lang.Class<? extends ActiveRecord> target, java.lang.String properties)
          Sets belongs-to relation with specified properties.
 void belongsTo(java.lang.String target)
          Sets belongs-to relation.
 void belongsTo(java.lang.String target, java.lang.String properties)
          Sets belongs-to relation with specified properties.
 void belongsToCategory(java.lang.String category)
          Sets up a category with default id field and type field.
 void belongsToCategory(java.lang.String category, java.lang.String idField, java.lang.String typeField)
          Sets up a category.
 void clearAndSetData(java.util.Map<java.lang.String,?> inputDataMap)
          Sets column values by parsing input string nameValuePairs from a Map.
 void clearAndSetData(java.lang.String nameValuePairs)
          Sets column values by parsing input string nameValuePairs.
 boolean containsPrimaryKey(java.util.Map<java.lang.String,java.lang.Object> data)
          Checks if a data map contains primary key.
 ActiveRecord create()
          Creates the record in database and returns it.
 ActiveRecord create(boolean changedOnly)
          Creates the record in database and returns it.
 java.util.Map<java.lang.String,java.lang.Object> data()
          Returns the record data as map.
protected  void declaresExtraFields()
          Extra fields are not stored in database.
protected  void declaresProtectedFields()
          Data for the protected fields are not affected by massive setData method.
 void decrementCounter(BelongsToRecordRelation btr)
          Decrements counter field by 1.
 void decrementCounter(BelongsToRecordRelation btr, int amount)
          Decrements counter field by 1.
 void decrementCounter(java.lang.String counterFieldName)
          Decrements counter field by 1.
 void decrementCounter(java.lang.String counterFieldName, int amount)
          Decrements counter field by amount.
 int delete()
          Deletes the record based on the current primary key values.
 java.lang.String details()
          Shows details of the record.
 void freeze()
          Freezes the current record.
 Calculator getCalculator()
          Returns an instance of Calculations.
 java.lang.String getConnectionName()
          Returns the database connection name associated with this record.
protected  java.lang.String getDeleteSQL()
           
 java.lang.Object getField(int index)
          Returns plain data for a column index.
 java.lang.Object getField(java.lang.String fieldName)
          Returns plain data for a field.
 java.lang.Object[] getFields()
          Returns plain data of a row in a table.
 java.util.Map<java.lang.String,java.lang.Object> getFields(java.util.List<java.lang.String> columnNames)
          Returns a map of column name and value pairs.
 java.util.List<java.lang.String> getModifiedFields()
          Returns a list of modified field names.
 java.lang.String getPK()
          Returns the primary key string the record.
 java.util.Map<java.lang.String,java.lang.Object> getPrimaryKeyDataMap()
          Returns the data map for primary keys.
 java.lang.String[] getPrimaryKeyNames()
          Returns a string array of primary key names.
protected  java.util.Map<java.lang.String,java.lang.Object> getPrimaryKeyRules()
          Sets populating rules for primary keys.
 RecordRelation getRecordRelation(java.lang.String associationId)
          Returns a RecordRelation related to the target model.
 java.lang.String getRestfulId()
           Returns the restified id of the resource.
 java.util.Map<java.lang.String,java.lang.Object> getRestfulIdMap()
          Returns the data map for the restified id.
 java.lang.String[] getRestfulIdNames()
          Returns column names corresponding to the restified id value returned by the getRestfulId method.
 RowInfo getRowInfo()
          Returns record meta data.
 java.lang.String getSimpleTableName()
          Returns a simple version of the table name.
 java.lang.String getTableName()
           Returns a full table name in the database.
 ValidationResults getValidationResults()
          Returns the ValidationResults instance of this record.
 void hasMany(java.lang.Class<? extends ActiveRecord> target)
          Sets has-many relation
 void hasMany(java.lang.Class<? extends ActiveRecord> target, java.lang.String properties)
          Sets has-many relation with specified properties.
 void hasMany(java.lang.String targets)
          Sets has-many relation.
 void hasMany(java.lang.String targets, java.lang.String properties)
          Sets has-many relation with specified properties.
 void hasManyInCategoryThrough(java.lang.Class<? extends ActiveRecord>[] targets, java.lang.String category, java.lang.Class<? extends ActiveRecord> through)
          This method adds a bunch of methods in many classes.
 void hasManyInCategoryThrough(java.lang.Class<? extends ActiveRecord>[] targets, java.lang.String category, java.lang.Class<? extends ActiveRecord> through, java.util.Map<java.lang.String,java.lang.Object>[] acJoinInputs, java.lang.String[] abProperties, java.lang.String[] types, java.lang.String relationType, java.lang.String[] bcProperties, java.util.Map<java.lang.String,java.lang.Object>[] bcJoinInputs, java.lang.String[] cbProperties, java.lang.String[] baProperties)
          This method adds a bunch of methods in many classes.
 void hasManyThrough(java.lang.Class<? extends ActiveRecord> target, java.lang.Class<? extends ActiveRecord> through)
          Sets has-many-through relation.
 void hasManyThrough(java.lang.Class<? extends ActiveRecord> target, java.lang.Class<? extends ActiveRecord> through, java.lang.String properties)
          Sets has-many-through relation.
 void hasManyThrough(java.lang.Class<? extends ActiveRecord> target, java.lang.Class<? extends ActiveRecord> through, java.lang.String properties, java.util.Map<java.lang.String,java.lang.Object> joinInputs)
          Sets has-many-through relation.
 void hasManyThrough(java.lang.String targets, java.lang.String throughAssociationId)
          Sets has-many-through relation.
 void hasManyThrough(java.lang.String targets, java.lang.String throughAssociationId, java.lang.String properties)
          Sets has-many-through relation with specified properties.
 void hasManyThrough(java.lang.String targets, java.lang.String throughAssociationId, java.lang.String properties, java.util.Map<java.lang.String,java.lang.Object> joinInputs)
          Sets has-many-through relation with specified properties and join through table data.
 void hasOne(java.lang.Class<? extends ActiveRecord> target)
          Sets has-one relation
 void hasOne(java.lang.Class<? extends ActiveRecord> target, java.lang.String properties)
          Sets has-one relation with specified properties.
 void hasOne(java.lang.String targetModelName)
          Sets has-one relation.
 void hasOne(java.lang.String target, java.lang.String properties)
          Sets has-one relation with specified properties.
 boolean hasPrimaryKey()
          Returns true if the record has primary key.
 void incrementCounter(BelongsToRecordRelation btr)
          Increments counter field by 1.
 void incrementCounter(BelongsToRecordRelation btr, int amount)
          Increments counter field by amount.
 void incrementCounter(java.lang.String counterFieldName)
          Increments counter field by 1.
 void incrementCounter(java.lang.String counterFieldName, int amount)
          Increments counter field by amount.
protected  ActiveRecord internal_create(boolean changedOnly)
          Creates the record in database and returns it.
 boolean isChildOf(ActiveRecord parent)
          Checks if an instance belongs to another record.
 boolean isColumnField(java.lang.String fieldName)
          Returns true if the field is a database table field.
 boolean isDependentOf(ActiveRecord parent)
          Check if this record is a dependent of a specific record.
 boolean isDirty()
          Indicates if the current record has been modified and unsaved to database.
 boolean isExtraField(java.lang.String fieldName)
          Returns true if the field is an extra field.
 boolean isFieldChanged(java.lang.String fieldName)
          Checks if a field is changed.
 boolean isFreezed()
          Indicates if the current record is freezed
 boolean isHomeInstance()
          Indicates if the current instance is a home instance.
 boolean isLegalField(java.lang.String fieldName)
          Checks whether a field is a legal field of this model.
 boolean isNewRecord()
          Indicates if the current record is a new record--not in database yet.
 boolean isPKDependentOf(java.lang.Class<? extends ActiveRecord> parentClz)
          Check if this record is a dependent of a specific record type through primary key.
 boolean isReadOnlyColumn(java.lang.String colName)
          Checks whether a column is a readonly column.
 boolean isRequiredColumn(java.lang.String colName)
          Checks whether a column is a required column.
 boolean isValid()
          Returns true if the record has no error.
protected  void processAutoAuditCreate()
          Do something for the auto-audit update fields.
protected  void processAutoAuditUpdate()
          Do something for the auto-audit update fields.
 void registerRelations()
          Subclass need to override this method by calling proper relationship setup methods: hasOne, belongsTo, hasMany, hasManyThrough, etc.
 void reload()
          Reloads the current record based on its primary key values.
 void save()
          Saves the current record.
 void save(boolean changedOnly)
           Saves the current record.
 void saveAndReload()
          Saves the current record and then reloads from database.
 void setData(int index, java.lang.Object columnData)
          Sets column data for a column index.
 void setData(java.util.Map<java.lang.String,?> inputDataMap)
          Sets column values by parsing input string nameValuePairs from a Map.
 void setData(java.lang.String nameValuePairs)
          Sets column values by parsing input string nameValuePairs
 void setData(java.lang.String fieldName, java.lang.Object fieldData)
          Sets data for a field.
protected  void setExtraFields(java.lang.String fields)
          Sets fields to be extra.
 void setPrimaryKey(java.util.Set<java.lang.String> primaryKeyNames)
          Sets primary key columns for the record
protected  void setProtectedFields(java.lang.String fields)
          Sets fields to be protected.
 void setReadOnlyColumn(java.lang.String readOnlyColumnName)
          Sets a column to be readonly.
 void setReadOnlyColumns(java.util.Set<java.lang.String> readOnlyColumnNames)
          Sets read-only columns.
 void setRecordRelation(java.lang.String associationId, RecordRelation rr)
          Sets a RecordRelation related to the target model.
 void setRestfulId(java.lang.String id)
          Sets the id value of the resource.
 java.lang.String toJSON()
          Returns a JSON representation of the object.
 java.util.Map<java.lang.String,java.lang.Object> toMap()
          Returns a Map representation of the record.
 java.lang.String toString()
          Returns a string representation of the record.
 java.lang.String toXML()
          Returns an XML representation of the object.
 int update()
          Updates the record.
 int update(boolean changedOnly)
           Updates the record.
 void updateCounters(java.util.Map<java.lang.String,? extends java.lang.Number> counters)
          Updates counters Counters map contains the names of the fields to update as keys and the amount to update the field by as values.
 void updateField(java.lang.String field, java.lang.Object value)
          Updates a single field and saves the record.
 void updateFields(java.util.Map<java.lang.String,?> fieldData)
          Updates all the fields contained in the map for a record (row) in database
 void validatesRecord()
           Subclass must override this method in order to provide a meaningful validation.
 void validatesRecordBeforeCreate()
          This delegates to validatesRecord().
 void validatesRecordBeforeDelete()
          The default implementation actually does nothing.
 void validatesRecordBeforeSave()
          This delegates to validatesRecord().
 void validatesRecordBeforeUpdate()
          This delegates to validatesRecord().
 ModelValidators validators()
          Returns an instance of Validators.
 void verifyExistenceOfField(java.lang.String fieldName)
          Checks if a field name exists in an ActiveRecord class.
 
Methods inherited from class com.scooterframework.orm.activerecord.ActiveRecordClass
average, average, calculate, columnNames, columns, connectionName, count, count, count, deleteAll, deleteAll, deleteAll, deleteById, deleteById, deleteByPK, deleteByPrimaryKeyMap, deleteBySQL, deleteBySQL, deleteBySQLKey, deleteBySQLKey, findAll, findAllBy, findAllBy, findAllBy, findAllBySQL, findAllBySQL, findAllBySQLKey, findAllBySQLKey, findById, findById, findByPK, findByRESTfulId, findFirst, findFirstBy, findLast, findLastBy, groupBy, having, homeInstance, includes, includes, includes, limit, maximum, maximum, minium, minium, newRecord, offset, orderBy, page, primaryKeyNames, readOnlyColumnNames, rowInfo, simpleTableName, sum, sum, tableName, updateAll, updateAll, updateAll, updateBySQL, updateBySQL, updateBySQLKey, updateBySQLKey, where, where, where
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

ActiveRecord

public ActiveRecord()

Constructs an instance of ActiveRecord.

The created instance is based on meta info for table as returned by getTableName() and database connection name as returned by getConnectionName().

This constructor will populate the meta info of the record and its table. The table name defaults to short class name. For example, if the model class name is com.example.models.User, the default table name for this class is posts or CRM_users_US if there are prefix CRM_ and suffix _US for all tables as specified in configuration file.

See description of ActiveRecord(String connectionName, String tableName) constructor.


ActiveRecord

public ActiveRecord(java.lang.String tableName)

Constructs an instance of ActiveRecord.

The created instance is based on meta info for tableName and database connection name as returned by getConnectionName().

This constructor will populate the meta info of the record and its table.

tableName is table name of the record. The the prefix and suffix of the database table name may be removed. For example, if a table name is CRM_users_US which has a prefix CRM_ and a suffix _US, the slim table name used here can just be users.

See description of ActiveRecord(String connectionName, String tableName) constructor.

Parameters:
tableName - table name of the record.

ActiveRecord

public ActiveRecord(java.lang.String connectionName,
                    java.lang.String tableName)

Constructs an instance of ActiveRecord for a specific database connection.

This constructor will populate the meta info of the record and its table.

connectionName is database connection name. For example, for the following entry in database.properties file, the connectionName is jpetstore:

                database.connection.jpetstore=\
                                driver=oracle.jdbc.driver.OracleDriver,\
                                url=jdbc:oracle:thin:@127.0.0.1:1521:jpetstore,\
                                username=scott,\
                                password=tiger
 

tableName is table name of the record. The the prefix and suffix of the database table name may be removed. For example, if a table name is CRM_users_US which has a prefix CRM_ and a suffix _US, the table name used here can just be users.

Parameters:
connectionName - database connection name.
tableName - table name of the record.
Method Detail

getConnectionName

public java.lang.String getConnectionName()

Returns the database connection name associated with this record.

By default, this method returns the default database connection name as defined in database.properties file. Subclass can override this method to link this ActiveRecord class to other database connection names defined in the database.properties file.

Returns:
database connection name

getPK

public java.lang.String getPK()

Returns the primary key string the record. This method is the same as the getRestfulId method.

Returns:
primary key String

getRestfulId

public java.lang.String getRestfulId()

Returns the restified id of the resource.

By default, this method returns a string of the primary key value of the record. If the primary key is a composite key, a separator (DatabaseConfig.PRIMARY_KEY_SEPARATOR) is used to link values of the key fields. The order of the fields of a composite primary key is defined by the getRestfulIdNames method.

If the underlying data does not have primary key, then all columns of the data are used to compute the id.

Subclass may override this method if a customized string format is required.

Specified by:
getRestfulId in interface RESTified
Returns:
id String

getRestfulIdNames

public java.lang.String[] getRestfulIdNames()
Returns column names corresponding to the restified id value returned by the getRestfulId method. By default, the order of the field names are obtained from the getPrimaryKeyNames method. Subclass may override this method if a customized string array is required.

Specified by:
getRestfulIdNames in interface RESTified
Returns:
string array of fields behind the id

getRestfulIdMap

public java.util.Map<java.lang.String,java.lang.Object> getRestfulIdMap()
Returns the data map for the restified id. By default, the keys in the map are primary key column names in lower case.

Specified by:
getRestfulIdMap in interface RESTified
Returns:
map of restified id data

setRestfulId

public void setRestfulId(java.lang.String id)

Sets the id value of the resource. The format of the id string must follow the pattern of the corresponding id config. If the id is backed by a composite primary key, a separator (DatabaseConfig.PRIMARY_KEY_SEPARATOR) must be used to link values of each primary key column.

 Examples:
   id string          id config array         description
   ---------          ---------------         -------
     0001             [id]                    an order with id 0001
     0001-99          [order_id, id]          an item with id 99 on the order with id 0001

 

Specified by:
setRestfulId in interface RESTified
Parameters:
id -

getRowInfo

public RowInfo getRowInfo()
Returns record meta data.

Returns:
RowInfo object of a table row
See Also:
RowInfo

getFields

public java.lang.Object[] getFields()
Returns plain data of a row in a table.

Returns:
an array of objects

getField

public java.lang.Object getField(int index)
Returns plain data for a column index.

Parameters:
index - column index like 0, 1, 2, ...
Returns:
a data object for the column

getField

public java.lang.Object getField(java.lang.String fieldName)
Returns plain data for a field.

Parameters:
fieldName - name of a model field
Returns:
a data object for the field

getFields

public java.util.Map<java.lang.String,java.lang.Object> getFields(java.util.List<java.lang.String> columnNames)
Returns a map of column name and value pairs.

Parameters:
columnNames - names of a database table column
Returns:
a map of column name and value pairs

setPrimaryKey

public void setPrimaryKey(java.util.Set<java.lang.String> primaryKeyNames)
Sets primary key columns for the record


setReadOnlyColumn

public void setReadOnlyColumn(java.lang.String readOnlyColumnName)

Sets a column to be readonly.

Sometimes columns like "entry_user, entry_dt, update_user, update_dt or xxx_count" are readonly. They will be updated by other database mechanisms.


setReadOnlyColumns

public void setReadOnlyColumns(java.util.Set<java.lang.String> readOnlyColumnNames)

Sets read-only columns.

Sometimes columns like "entry_user, entry_dt, update_user, update_dt" are readonly. They will be updated by other database mechanisms.


isReadOnlyColumn

public boolean isReadOnlyColumn(java.lang.String colName)
Checks whether a column is a readonly column.

Parameters:
colName - the column name to be checked.
Returns:
true if the column is readonly

isRequiredColumn

public boolean isRequiredColumn(java.lang.String colName)
Checks whether a column is a required column. Data for a required column cannot be set to null.

Parameters:
colName - the column name to be checked.
Returns:
true if the column is required.

isDirty

public boolean isDirty()
Indicates if the current record has been modified and unsaved to database.


isNewRecord

public boolean isNewRecord()
Indicates if the current record is a new record--not in database yet.


isFreezed

public boolean isFreezed()
Indicates if the current record is freezed


freeze

public void freeze()
Freezes the current record.


isHomeInstance

public boolean isHomeInstance()
Indicates if the current instance is a home instance.


create

public ActiveRecord create()

Creates the record in database and returns it.

This method is the same as create(true).


create

public ActiveRecord create(boolean changedOnly)

Creates the record in database and returns it.

If changedOnly is true, only changed fields are included in SQL query.

This method calls beforeCreate() before the real create, and afterCreate() after the create execution.

Parameters:
changedOnly - true if only changed fields are included in SQL query
Returns:
a new ActiveRecord instance.

updateField

public void updateField(java.lang.String field,
                        java.lang.Object value)
Updates a single field and saves the record.

Parameters:
field - a field name
value - value of the field

updateFields

public void updateFields(java.util.Map<java.lang.String,?> fieldData)
Updates all the fields contained in the map for a record (row) in database

Parameters:
fieldData - a map of field and its data pairs

updateCounters

public void updateCounters(java.util.Map<java.lang.String,? extends java.lang.Number> counters)
Updates counters Counters map contains the names of the fields to update as keys and the amount to update the field by as values.

Parameters:
counters -

incrementCounter

public void incrementCounter(BelongsToRecordRelation btr)
Increments counter field by 1.

Parameters:
btr - BelongsToRecordRelation

incrementCounter

public void incrementCounter(java.lang.String counterFieldName)
Increments counter field by 1.

Parameters:
counterFieldName -

incrementCounter

public void incrementCounter(BelongsToRecordRelation btr,
                             int amount)
Increments counter field by amount.

Parameters:
btr - BelongsToRecordRelation
amount -

incrementCounter

public void incrementCounter(java.lang.String counterFieldName,
                             int amount)
Increments counter field by amount.

Parameters:
counterFieldName -
amount -

decrementCounter

public void decrementCounter(BelongsToRecordRelation btr)
Decrements counter field by 1.

Parameters:
btr - BelongsToRecordRelation

decrementCounter

public void decrementCounter(java.lang.String counterFieldName)
Decrements counter field by 1.

Parameters:
counterFieldName -

decrementCounter

public void decrementCounter(BelongsToRecordRelation btr,
                             int amount)
Decrements counter field by 1.

Parameters:
btr - BelongsToRecordRelation
amount -

decrementCounter

public void decrementCounter(java.lang.String counterFieldName,
                             int amount)
Decrements counter field by amount.

Parameters:
counterFieldName -
amount -

update

public int update()

Updates the record.

This method is the same as update(true).


update

public int update(boolean changedOnly)

Updates the record. If changedOnly is true, only changed fields are included in SQL query.

If there is no primary key defined for the model, data from all columns will be used as update conditions.

This method calls beforeUpdate before the real update, and afterUpdate after the update execution.

Parameters:
changedOnly - true if only changed fields are included in SQL query
Returns:
number of records updated

delete

public int delete()

Deletes the record based on the current primary key values.

If there is no primary key defined for the model, data from all columns will be used as delete conditions.

Returns:
int number of records deleted

reload

public void reload()
Reloads the current record based on its primary key values.


save

public void save()

Saves the current record.

The SQL query includes only those fields that are changed.

This method is the same as save(true).


save

public void save(boolean changedOnly)

Saves the current record.

If changedOnly is true, the SQL query includes only those fields that are changed; otherwise, includes all fields.

If the record exists , this method uses update(boolean), otherwise create(true).

This method calls beforeSave before the real save, and afterSave() after the save execution.

Parameters:
changedOnly - true if only changed fields are included in SQL query

saveAndReload

public void saveAndReload()

Saves the current record and then reloads from database.

This method is useful when other process such as database trigger may change the record.


clearAndSetData

public void clearAndSetData(java.lang.String nameValuePairs)

Sets column values by parsing input string nameValuePairs.

String nameValuePairs has the following format for example:

          firstName=John, lastName=Doe, age=10,...
       or firstName=John|lastName=Doe|age=10|...
       or firstName=John&lastName=Doe&age=10&...
 
You can use either ',', or '|' or '&' to separate each condition.

The name of the data entry in the nameValuePairs is corresponding to a column name in the RowInfo object. If the name is not a column name, its value is ignored. If the column name is not in the names of the nameValuePairs, the column data is set to null.

If a column name is protected, its data is unaffected. Use setData method to set its data.


clearAndSetData

public void clearAndSetData(java.util.Map<java.lang.String,?> inputDataMap)

Sets column values by parsing input string nameValuePairs from a Map.

The key of the data entry in the Map is corresponding to a column name in the RowInfo object. If the key is not a column name, its value is ignored. If the column name is not in the key set of the Map, the column data is set to null.

If a column name is protected, its data is unaffected. Use setData method to set its data.


data

public java.util.Map<java.lang.String,java.lang.Object> data()

Returns the record data as map. The keys in the map are field names in upper case. An empty map is returned if the underline data is not retrieved or the record is new.

Returns:
map of record data

setData

public void setData(java.lang.String nameValuePairs)

Sets column values by parsing input string nameValuePairs

String nameValuePairs has the following format for example:

          firstName=John, lastName=Doe, age=10,...
       or firstName=John|lastName=Doe|age=10|...
       or firstName=John&lastName=Doe&age=10&...
 
You can use either ',', or '|' or '&' to separate each condition.

The name of the data entry in the nameValuePairs is corresponding to a column name in the RowInfo object. If the name is not a column name, its value is ignored. If the column name is not in the names of the nameValuePairs, the column data is not updated. To set those column data to null when the column name is not in the key set, use the clearAndSetData method.

This method does not save data to database. Use save() or create() or update() to save data to database.

If a column name is protected, its data is unaffected. Use setData method to set its data.


setData

public void setData(java.util.Map<java.lang.String,?> inputDataMap)

Sets column values by parsing input string nameValuePairs from a Map.

The key of the data entry in the Map is corresponding to a column name in the RowInfo object. If the key is not a column name, its value is ignored. If the column name is not in the key set of the Map, or the column is readonly or not writable, or is primary key of an existing record, the column data is not updated.

To set those column data to null when the column name is not in the key set, use the clearAndSetData method.

This method does not save data to database. Use save() or create() or update() to save data to database.

If a column name is protected, its data is unaffected.


setData

public void setData(int index,
                    java.lang.Object columnData)

Sets column data for a column index.

Index starts from 0: 0, 1, 2, ...

This method does not save data to database. Use save() or create() or update() to save data to database.


setData

public void setData(java.lang.String fieldName,
                    java.lang.Object fieldData)

Sets data for a field.

If there is no such a field, an InvalidColumnNameException will be thrown.

This method does not save data to database. Use save() or create() or update() to save data to database.


containsPrimaryKey

public boolean containsPrimaryKey(java.util.Map<java.lang.String,java.lang.Object> data)
Checks if a data map contains primary key.

Parameters:
data - Map of input data
Returns:
boolean state indicates if the data map contains primary field(s)

hasPrimaryKey

public boolean hasPrimaryKey()
Returns true if the record has primary key.


getPrimaryKeyNames

public java.lang.String[] getPrimaryKeyNames()
Returns a string array of primary key names.

Returns:
String[]

getPrimaryKeyDataMap

public java.util.Map<java.lang.String,java.lang.Object> getPrimaryKeyDataMap()
Returns the data map for primary keys. The keys in the map are primary key column names in lower case. An empty map is returned if the underline data is not retrieved or the record is new.

Returns:
map of primary key data

associated

public AssociatedRecord associated(java.lang.Class<? extends ActiveRecord> target)
Returns an AssociatedRecord instance of a specific class type.

Parameters:
target - class of the associated record
Returns:
the AssociatedRecord instance

associated

public AssociatedRecord associated(java.lang.Class<? extends ActiveRecord> target,
                                   boolean refresh)
Returns an AssociatedRecord instance of a specific class type.

Parameters:
target - class of the associated record
refresh - true if reload database data
Returns:
the AssociatedRecord instance

associated

public AssociatedRecord associated(java.lang.Class<? extends ActiveRecord> target,
                                   java.lang.String options)

Returns an AssociatedRecord instance of a specific class type.

See top of this class for options examples.

Parameters:
target - class of the associated record
options - A string of options.
Returns:
the AssociatedRecord instance

associated

public AssociatedRecord associated(java.lang.Class<? extends ActiveRecord> target,
                                   java.lang.String options,
                                   boolean refresh)

Returns an AssociatedRecord instance of a specific class type.

See top of this class for options examples.

Parameters:
target - class of the associated record
options - A string of options.
refresh - true if reload database data
Returns:
the AssociatedRecord instance

associated

public AssociatedRecord associated(java.lang.String associationId)

Returns an AssociatedRecord instance.

The associationId is the name of the belongs-to or has-one relation defined in the class.

Parameters:
associationId - association id
Returns:
the AssociatedRecord instance

associated

public AssociatedRecord associated(java.lang.String associationId,
                                   boolean refresh)

Returns an AssociatedRecord instance.

The associationId is the name of the belongs-to or has-one relation defined in the class.

Parameters:
associationId - association id
refresh - true if reload database data
Returns:
the AssociatedRecord instance

associated

public AssociatedRecord associated(java.lang.String associationId,
                                   java.lang.String options)

Returns an AssociatedRecord instance.

The associationId is the name of the belongs-to or has-one relation defined in the class.

See top of this class for options examples.

Parameters:
associationId - association id
options - A string of options.
Returns:
the AssociatedRecord instance

associated

public AssociatedRecord associated(java.lang.String associationId,
                                   java.lang.String options,
                                   boolean refresh)

Returns an AssociatedRecord instance.

The associationId is the name of the belongs-to or has-one relation defined in the class.

See top of this class for options examples.

Parameters:
associationId - association id
options - A string of options.
refresh - true if reload database data
Returns:
the AssociatedRecord instance

allAssociated

public AssociatedRecords allAssociated(java.lang.Class<? extends ActiveRecord> target)
Returns an AssociatedRecords instance of a specific class type.

Parameters:
target - class of the associated records
Returns:
the AssociatedRecords instance

allAssociated

public AssociatedRecords allAssociated(java.lang.Class<? extends ActiveRecord> target,
                                       boolean refresh)
Returns an AssociatedRecords instance of a specific class type.

Parameters:
target - class of the associated records
refresh - true if reload database data
Returns:
the AssociatedRecords instance

allAssociated

public AssociatedRecords allAssociated(java.lang.Class<? extends ActiveRecord> target,
                                       java.lang.String options)

Returns an AssociatedRecords instance of a specific class type.

See top of this class for options examples.

Parameters:
target - class of the associated records
options - A string of options.
Returns:
the AssociatedRecords instance

allAssociated

public AssociatedRecords allAssociated(java.lang.Class<? extends ActiveRecord> target,
                                       java.lang.String options,
                                       boolean refresh)
Returns an AssociatedRecords instance of a specific class type.

Parameters:
target - class of the associated records
options - A string of options.
refresh - true if reload database data
Returns:
the AssociatedRecords instance

allAssociated

public AssociatedRecords allAssociated(java.lang.String associationId)

Returns an AssociatedRecords instance.

The associationId is the name of the has-many or has-many-through relation defined in the class.

Parameters:
associationId - association id
Returns:
the AssociatedRecords instance

allAssociated

public AssociatedRecords allAssociated(java.lang.String associationId,
                                       boolean refresh)

Returns an AssociatedRecords instance.

The associationId is the name of the has-many or has-many-through relation defined in the class.

Parameters:
associationId - association id
refresh - true if reload database data
Returns:
the AssociatedRecords instance

allAssociated

public AssociatedRecords allAssociated(java.lang.String associationId,
                                       java.lang.String options)

Returns an AssociatedRecords instance.

The associationId is the name of the has-many or has-many-through relation defined in the class.

See top of this class for options examples.

Parameters:
associationId - association id
options - A string of options.
Returns:
the AssociatedRecords instance

allAssociated

public AssociatedRecords allAssociated(java.lang.String associationId,
                                       java.lang.String options,
                                       boolean refresh)

Returns an AssociatedRecords instance.

The associationId is the name of the has-many or has-many-through relation defined in the class.

See top of this class for options examples.

Parameters:
associationId - association id
options - A string of options.
refresh - true if reload database data
Returns:
the AssociatedRecords instance

allAssociatedInCategory

public AssociatedRecordsInCategory allAssociatedInCategory(java.lang.String category)
Returns an AssociatedRecordsInCategory instance.

Parameters:
category - name of the category
Returns:
the AssociatedRecordsInCategory instance

allAssociatedInCategory

public AssociatedRecordsInCategory allAssociatedInCategory(java.lang.String category,
                                                           boolean refresh)
Returns an AssociatedRecordsInCategory instance.

Parameters:
category - name of the category
refresh - true if reload database data
Returns:
the AssociatedRecordsInCategory instance

allAssociatedInCategory

public AssociatedRecordsInCategory allAssociatedInCategory(java.lang.String category,
                                                           java.lang.String type)
Returns an AssociatedRecordsInCategory instance.

Parameters:
category - name of the category
type - type name in the category
Returns:
the AssociatedRecordsInCategory instance

allAssociatedInCategory

public AssociatedRecordsInCategory allAssociatedInCategory(java.lang.String category,
                                                           java.lang.String type,
                                                           boolean refresh)
Returns an AssociatedRecordsInCategory instance.

Parameters:
category - name of the category
type - type name in the category
refresh - true if reload database data
Returns:
the AssociatedRecordsInCategory instance

associatedInCategory

public AssociatedRecord associatedInCategory(java.lang.String category)
Returns associated record of this join model based on the type value of the type field. For example, tagging.associatedInCategory("taggable").

Parameters:
category - name of the category
Returns:
an associated record for the category

associatedInCategory

public AssociatedRecord associatedInCategory(java.lang.String category,
                                             boolean refresh)
Returns associated record of this join model based on the type value of the type field. For example, tagging.associatedInCategory("taggable", true).

Parameters:
category - name of the category
refresh - true if reload database data
Returns:
an associated record for the category

isPKDependentOf

public boolean isPKDependentOf(java.lang.Class<? extends ActiveRecord> parentClz)
Check if this record is a dependent of a specific record type through primary key. The following must be satisfied:
  1. There must be a belongsTo relation between this record and the parent model type.
  2. The child record has a primary key and part or whole of that key is the primary key of the parent model type.
For example, EMPLOYEE (pk=id) and DEPENDENT (pk=id, emp_id);

Parameters:
parentClz - A potential parent model type
Returns:
true if it is a true parent.

isDependentOf

public boolean isDependentOf(ActiveRecord parent)
Check if this record is a dependent of a specific record. To be a dependent of a specific record type, the following must be satisfied:
  1. There must be a belongsTo relation between this record and the parent model type.
  2. The cascade property of the parent model must be cascade delete or
  3. The child record has a primary key and part or whole of the key is the primary key of the parent model.
  4. The record's foreign key must hold parent record's primary key value.
For example, EMPLOYEE (pk=id) and DEPENDENT (pk=id, emp_id);

Parameters:
parent - A potential parent model
Returns:
true if it is a true parent.

isChildOf

public boolean isChildOf(ActiveRecord parent)
Checks if an instance belongs to another record. To belong to a record, the following conditions must be satisfied:
  1. There must be a belongsTo relation between this record and the potential parent record.
  2. The record's foreign key must hold parent record's primary key value.

Parameters:
parent -
Returns:
true if the instance is a child of another record

registerRelations

public void registerRelations()
Subclass need to override this method by calling proper relationship setup methods: hasOne, belongsTo, hasMany, hasManyThrough, etc.


belongsTo

public void belongsTo(java.lang.Class<? extends ActiveRecord> target)

Sets belongs-to relation.

The association id is the model name of the target class.

Parameters:
target - the class that is associated with.

belongsTo

public void belongsTo(java.lang.Class<? extends ActiveRecord> target,
                      java.lang.String properties)

Sets belongs-to relation with specified properties.

The association id of the relation is the model name of the target class.

Parameters:
target - the class that is associated with.
properties - string of association properties.

belongsTo

public void belongsTo(java.lang.String target)
Sets belongs-to relation.

Parameters:
target - model name of the associated class.

belongsTo

public void belongsTo(java.lang.String target,
                      java.lang.String properties)
Sets belongs-to relation with specified properties.

target parameter can be either the model name of the target or a descriptive string of the target. In the latter case, the properties parameter must contain key model to indicate the model name of the target unless it can be derived from the target name.

 Example:
      target    properties
      ------    ----------
      friend    model:person
 

Example property string: In a property string, each name-value pair is separated by ';' character, while within each name-value pair, name and value strings are separated by ':' character. For example, a property string like the following

      mapping: order_id=id;
      conditions_sql: id in (1, 2, 3); include: category, user;
      order_by: first_name, salary desc; cascade: delete
 
will be converted to a HashMap with the following entries:
      key                 value
      -------------       ---------------
      mapping         =>  order_id=id
      conditions_sql  =>  id in (1, 2, 3)
      include         =>  category, user
      order_by        =>  first_name, salary desc
      cascade         =>  delete
 
For a complete list of properties, see top of the class or developer guide.

Parameters:
target - target name of the associated class.
properties - association properties.

belongsToCategory

public void belongsToCategory(java.lang.String category)

Sets up a category with default id field and type field.

This method assumes that the id field is ${category}_id and the type field is ${category}_type.

Parameters:
category - name of the category

belongsToCategory

public void belongsToCategory(java.lang.String category,
                              java.lang.String idField,
                              java.lang.String typeField)
Sets up a category.

Parameters:
idField - name of the id column of the category center table
typeField - name of the type column of the category center table
category - name of the category

hasOne

public void hasOne(java.lang.Class<? extends ActiveRecord> target)
Sets has-one relation

Parameters:
target - the class that is associated with.

hasOne

public void hasOne(java.lang.Class<? extends ActiveRecord> target,
                   java.lang.String properties)

Sets has-one relation with specified properties.

The association id of the relation is the model name of the target class.

Parameters:
target - the class that is associated with.
properties - string of association properties.

hasOne

public void hasOne(java.lang.String targetModelName)
Sets has-one relation.

Parameters:
targetModelName - model name of the associated class.

hasOne

public void hasOne(java.lang.String target,
                   java.lang.String properties)
Sets has-one relation with specified properties.

target parameter can be either the model name of the target or a descriptive string of the target. In the latter case, the properties parameter must contain key model to indicate the model name of the target.

 Example:
      target    properties
      ------    ----------
      setting   model:profile
 

Example property string: In a property string, each name-value pair is separated by ';' character, while within each name-value pair, name and value strings are separated by ':' character. For example, a property string like the following

      mapping: id=order_id;
      conditions_sql: id in (1, 2, 3); include: category, user;
      order_by: first_name, salary desc; cascade: delete
 
will be converted to a HashMap with the following entries:
      key                 value
      -------------       ---------------
      mapping         =>  id=order_id
      conditions_sql  =>  id in (1, 2, 3)
      include         =>  category, user
      order_by        =>  first_name, salary desc
      cascade         =>  delete
 
For a complete list of properties, see top of the class or developer guide.

Parameters:
target - target name of the associated class.
properties - association properties.

hasMany

public void hasMany(java.lang.Class<? extends ActiveRecord> target)
Sets has-many relation

Parameters:
target - the class that is associated with.

hasMany

public void hasMany(java.lang.Class<? extends ActiveRecord> target,
                    java.lang.String properties)

Sets has-many relation with specified properties.

The association id of the relation is the plural form of the model name of the target class.

Parameters:
target - the class that is associated with.
properties - string of association properties.

hasMany

public void hasMany(java.lang.String targets)
Sets has-many relation.

Parameters:
targets - plural form of a model name of the associated class.

hasMany

public void hasMany(java.lang.String targets,
                    java.lang.String properties)
Sets has-many relation with specified properties.

targets parameter can be either a plural form of the model name of the target or a descriptive string of the target. In the latter case, the properties parameter must contain key model to indicate the model name of the target.

 Example:
      targets    properties
      -------    ----------
      people    model:person
 

Example property string: In a property string, each name-value pair is separated by ';' character, while within each name-value pair, name and value strings are separated by ':' character. For example, a property string like the following

      mapping: id=order_id;
      conditions_sql: id in (1, 2, 3); include: category, user;
      order_by: first_name, salary desc; cascade: delete
 
will be converted to a HashMap with the following entries:
      key                 value
      -------------       ---------------
      mapping         =>  id=order_id
      conditions_sql  =>  id in (1, 2, 3)
      include         =>  category, user
      order_by        =>  first_name, salary desc
      cascade         =>  delete
 
For a complete list of properties, see top of the class or developer guide.

Parameters:
targets - plural form of target name of the associated class.
properties - association properties.

hasManyThrough

public void hasManyThrough(java.lang.Class<? extends ActiveRecord> target,
                           java.lang.Class<? extends ActiveRecord> through)

Sets has-many-through relation.

This is equivalent to hasManyThrough(java.lang.String, java.lang.String) method with the plural form of the model name as the association name.

Parameters:
target - target class.
through - middleC class.

hasManyThrough

public void hasManyThrough(java.lang.Class<? extends ActiveRecord> target,
                           java.lang.Class<? extends ActiveRecord> through,
                           java.lang.String properties)

Sets has-many-through relation.

This is equivalent to hasManyThrough(java.lang.String, java.lang.String, java.lang.String) method with the plural form of the model name as the association name.

Parameters:
target - target class.
through - middleC class.
properties - properties string.

hasManyThrough

public void hasManyThrough(java.lang.Class<? extends ActiveRecord> target,
                           java.lang.Class<? extends ActiveRecord> through,
                           java.lang.String properties,
                           java.util.Map<java.lang.String,java.lang.Object> joinInputs)

Sets has-many-through relation.

This is equivalent to hasManyThrough(java.lang.String, java.lang.String, java.lang.String, java.util.Map) method with the plural form of the model name as the association name.

Parameters:
target - target class.
through - middleC class.
properties - properties string.
joinInputs - data map for the join table.

hasManyThrough

public void hasManyThrough(java.lang.String targets,
                           java.lang.String throughAssociationId)

Sets has-many-through relation.

There are two pre-requisits for setting up a has-many-through relation:

Parameters:
targets - plural form of target name of the associated class.
throughAssociationId - the name of the association that is in the middle.

hasManyThrough

public void hasManyThrough(java.lang.String targets,
                           java.lang.String throughAssociationId,
                           java.lang.String properties)

Sets has-many-through relation with specified properties.

There are two pre-requisits for setting up a has-many-through relation:

Example property string: In a property string, each name-value pair is separated by ';' character, while within each name-value pair, name and value strings are separated by ':' character.

For example, a property string like the following

      conditions_sql: id in (1, 2, 3); include: category, user;
      order_by: first_name, salary desc; cascade: delete
 
will be converted to a HashMap with the following entries:
      key                 value
      -------------       ---------------
      conditions_sql  =>  id in (1, 2, 3)
      include         =>  category, user
      order_by        =>  first_name, salary desc
      cascade         =>  delete
 
For a complete list of properties, see top of the class or developer guide.

Parameters:
targets - plural form of target name of the associated class.
throughAssociationId - the name of the association that is in the middle.
properties - properties string.

hasManyThrough

public void hasManyThrough(java.lang.String targets,
                           java.lang.String throughAssociationId,
                           java.lang.String properties,
                           java.util.Map<java.lang.String,java.lang.Object> joinInputs)

Sets has-many-through relation with specified properties and join through table data.

There are two pre-requisits for setting up a has-many-through relation:

See description of hasManyThrough(java.lang.String, java.lang.String, java.lang.String) method for details about properties.

Parameters:
targets - plural form of target name of the associated class.
throughAssociationId - the name of the association that is in the middle.
properties - properties string.
joinInputs - data map for the join table.

hasManyInCategoryThrough

public void hasManyInCategoryThrough(java.lang.Class<? extends ActiveRecord>[] targets,
                                     java.lang.String category,
                                     java.lang.Class<? extends ActiveRecord> through)
This method adds a bunch of methods in many classes.
  1. A has-many-through association from owner to each target class.
  2. A has-many association from each target to through class.
  3. A has-many-through association from each target to owner class.
  4. A belongs-to association from through to each target class.
In order to establish the associations, the method assumes the following:
  1. The type value of the category type column is the model name of each corresponding target class.
  2. The primary key of each target class is "id".
  3. The mapping string between each target class and through class is "id= category's id column".
  4. The association property from each target to through contains "cascade: delete".

If any of the above assumptions are not satisfied, you need to use the other hasManyInCategoryThrough method which gives you more control on specifying the associations.

Example usage:

Assuming there are image files and text files in a folder. We create three models: images, texts, folders. We also use linkings model to link folders with images and texts files. We will create the following classes:

  CREATE TABLE linkings (
      id INTEGER AUTO_INCREMENT,
      folder_id INTEGER,
      linkable_id INTEGER,
      linkable_type VARCHAR(20),
      PRIMARY KEY(id)
  )

  class Linking extends ActiveRecord {
      public void registerRelations() {
          belongsTo(Folder.class);
          belongsToCategory("linkable");
      }
  }

  class Folder extends ActiveRecord {
      public void registerRelations() {
          hasMany(Linking.class);
          hasManyInCategoryThrough(Folder.class,
                                   new Class[]{Image.class, Text.class},
                                   "linkable", Linking.class);
      }
  }

  class Image extends ActiveRecord {
  }

  class Text extends ActiveRecord {
  }
 
The following codes show how to get total of ownership for a customer:
      //Find all ownerships of a customer
      ActiveRecord customerHome = ActiveRecordUtil.getHomeInstance(Customer.class);
      ActiveRecord customer = customerHome.find("id=1");
      int total = customer.allAssociatedInCategory("ownerable").size();
 
It is also easy to add a dvd to the ownership of the customer:
      //Assign a dvd to a customer
      ActiveRecord dvdHome = ActiveRecordUtil.getHomeInstance(Dvd.class);
      ActiveRecord dvd = dvdHome.find("id=4");
      List dvds = customer.allAssociatedInCategory("ownerable").add(dvd).getRecords();
 

Parameters:
targets - array of target classes
category - the category which the targets act as
through - the middle join class between owner and targets

hasManyInCategoryThrough

public void hasManyInCategoryThrough(java.lang.Class<? extends ActiveRecord>[] targets,
                                     java.lang.String category,
                                     java.lang.Class<? extends ActiveRecord> through,
                                     java.util.Map<java.lang.String,java.lang.Object>[] acJoinInputs,
                                     java.lang.String[] abProperties,
                                     java.lang.String[] types,
                                     java.lang.String relationType,
                                     java.lang.String[] bcProperties,
                                     java.util.Map<java.lang.String,java.lang.Object>[] bcJoinInputs,
                                     java.lang.String[] cbProperties,
                                     java.lang.String[] baProperties)
This method adds a bunch of methods in many classes.
 
  • A has-many-through association from owner to each target class.
  • A has-many association from each target to through class.
  • A has-many-through association from each target to owner class.
  • A belongs-to association from through to each target class.
  • Assuming owner class is A, target class is B, through class is C,
     abProperties is join properties from A to B,
     bcProperties is join properties from B to C,
     cbProperties is join properties from C to B,
     baProperties is join properties from B to A.
     

    Parameters:
    targets - array of target classes
    category - the category which the targets act as
    through - the middle join class between owner and targets
    acJoinInputs - array of data map for the join through table.
    abProperties - properties from owner to target class
    types - array of join types in the category, default to model name
    relationType - either has-many or has-one
    bcProperties - array of properties from each target to through class
    bcJoinInputs - array of data map for the join through table.
    cbProperties - array of properties from through to each target class
    baProperties - array of properties from each target to owner class

    isColumnField

    public boolean isColumnField(java.lang.String fieldName)
    Returns true if the field is a database table field.

    Parameters:
    fieldName - the field name to check.
    Returns:
    boolean true if the field is a database table field.

    isExtraField

    public boolean isExtraField(java.lang.String fieldName)
    Returns true if the field is an extra field.

    Parameters:
    fieldName - the field name to check.
    Returns:
    boolean true if the field is an extra field.

    getModifiedFields

    public java.util.List<java.lang.String> getModifiedFields()
    Returns a list of modified field names.

    Returns:
    list of modified field names

    isFieldChanged

    public boolean isFieldChanged(java.lang.String fieldName)
    Checks if a field is changed.

    Parameters:
    fieldName - the field name to check
    Returns:
    true if the field is changed.

    isLegalField

    public boolean isLegalField(java.lang.String fieldName)
    Checks whether a field is a legal field of this model.

    Parameters:
    fieldName - the field name to check
    Returns:
    true if the field is either a column or an extra field.

    verifyExistenceOfField

    public void verifyExistenceOfField(java.lang.String fieldName)
    Checks if a field name exists in an ActiveRecord class.

    Parameters:
    fieldName - a field name

    getTableName

    public java.lang.String getTableName()

    Returns a full table name in the database. By default the table name is a short class name. Subclass may override this method to provide a more meaningful table name.

    The default table name is a short version of current class name. Java class name starts with capital letter. If the class name has more than one capital letter, an underscore is added as part of the table name.

     Examples:
    
          Class Name:                             Table Name:
          ---------------------------------------------------
          com.example.model.User                  users
          com.example.model.LineItem              line_items
          com.example.model.UserAccount           user_accounts
          com.example.model.UserURL               user_urls
     

    Returns:
    String table name

    getSimpleTableName

    public java.lang.String getSimpleTableName()
    Returns a simple version of the table name.

    For example, if the table name is "CRM_users_US" which has a prefix "CRM_" and a suffix "_US", the returned slim table name is just "users". Both the prefix and the suffix are removed in the return value.

    Returns:
    a simple version of table name.

    getPrimaryKeyRules

    protected java.util.Map<java.lang.String,java.lang.Object> getPrimaryKeyRules()

    Sets populating rules for primary keys.

    Subclass may override this method to use one of the four following ways to provide primary key values.

    There are four ways to set up the name-rule pair for primary key:

     1. Do nothing. This is the default. that means the database will
        autogenerate a primary key. This feature is available on MySQL, but
        not on Oracle yet. If you use this feature, that means the primary
        key can not be a composite field.
    
     2. If the primary key value is a result of SQL query,
        the entry may look like this:
                ("id", "sql=SELECT max(id)+1 FROM employee");
    
     3. If the primary key value is a result of a named SQL query,
        the entry may look like this:
                ("id", "sqlkey=employee_id_query");
        where the value "employee_id_query" is a named query in
        sql.properties file.
    
     4. Use a fixed value:
                Map("id", "1000");
     

    Returns:
    a data map for primary keys

    getDeleteSQL

    protected java.lang.String getDeleteSQL()

    declaresProtectedFields

    protected void declaresProtectedFields()

    Data for the protected fields are not affected by massive setData method.

    Subclass need to override this method by calling setProtectedFields method to declare protected fields.


    declaresExtraFields

    protected void declaresExtraFields()

    Extra fields are not stored in database.

    Subclass need to override this method by calling setExtraFields method to declare extra fields.


    beforeSetData

    protected void beforeSetData()
    Creates a backup copy of the current record data


    afterSetData

    protected void afterSetData(java.util.List<java.lang.String> modifiedColumnNames)
    Records those columns that are modified and sets dirty flag.

    Parameters:
    modifiedColumnNames -

    afterSetData

    protected void afterSetData(int columnIndex)
    Records the column index that is modified and sets dirty flag

    Parameters:
    columnIndex -

    afterSetData

    protected void afterSetData(java.lang.String columnName)
    Records the column that is modified and sets dirty flag

    Parameters:
    columnName -

    beforeFind

    protected void beforeFind()
    Do something before the record is found in database.


    afterFind

    protected void afterFind()
    Do something after the record is found in database.


    beforeCreate

    protected void beforeCreate()
    Do something before the record is created in database.


    afterCreate

    protected void afterCreate()
    Do something after the record is created in database.


    internal_create

    protected ActiveRecord internal_create(boolean changedOnly)
    Creates the record in database and returns it.


    beforeDelete

    protected void beforeDelete()
    Do something before the record is deleted in database.


    afterDelete

    protected void afterDelete()
    Do something after the record is deleted in database.


    beforeSave

    protected void beforeSave()
    Do something before the record is saved in database.


    afterSave

    protected void afterSave()
    Do something after the record is saved in database.


    beforeUpdate

    protected void beforeUpdate()
    Do something before the record is updated in database.


    afterUpdate

    protected void afterUpdate()
    Do something after the record is updated in database.


    processAutoAuditCreate

    protected void processAutoAuditCreate()

    Do something for the auto-audit update fields.

    Subclass can override this method if needed.


    processAutoAuditUpdate

    protected void processAutoAuditUpdate()

    Do something for the auto-audit update fields.

    Subclass can override this method if needed.


    actAsInCategory

    public void actAsInCategory(java.lang.String category,
                                java.lang.Class<? extends ActiveRecord> target)

    Acts as a certain type in a category.

    This method adds a hasMany association with the target in the owner class, and a belongsTo association in the target class.

    The target class is the center class of the category.

     Examples:
       owner class  => Image, File, Post
       category     => taggable
       target class => Tagging
     

    Parameters:
    category - the category this model performs
    target - the associated class

    actAsInCategory

    public void actAsInCategory(java.lang.String type,
                                java.lang.String category,
                                java.lang.Class<? extends ActiveRecord> target)

    Acts as a certain type in a category.

    This method adds a hasMany association with the target in the owner class, and a belongsTo association in the target class.

    This method assumes that you use "id" as primary key in the owner entity.

     Examples:
       owner class  => Image, File, Post
       type         => image, file, post
       category     => taggable
       target class => Tagging
     

    Parameters:
    type - the specific type this entity represents
    category - the category this entity performs
    target - the associated class

    actAsInCategory

    public void actAsInCategory(java.lang.String type,
                                java.lang.String category,
                                java.lang.String relationType,
                                java.lang.Class<? extends ActiveRecord> target,
                                java.lang.String bcProperties,
                                java.lang.String cbProperties)

    Acts as a certain type in a category.

    This method adds a hasMany (or hasOne) association with the target in the owner class, and a belongsTo association in the target class. The target class is the center of the category.

    Assuming owner class is B, target class is C, bcProperties is join properties from B to C, cbProperties is join properties from C to B.

     Examples:
       owner class  => Image, File, Post
       type         => image, file, post
       category     => taggable
       target class => Tagging
     

    Parameters:
    type - the specific type this entity represents in the category
    category - the category this entity performs
    relationType - either has-many or has-one
    target - the associated class
    bcProperties - properties of the has-many or has-one association from owner to target
    cbProperties - properties of the belongs-to association from target to owner

    getRecordRelation

    public RecordRelation getRecordRelation(java.lang.String associationId)

    Returns a RecordRelation related to the target model.

    The associationId is the name of the relation defined in the class.

    Parameters:
    associationId - association id
    Returns:
    a RecordRelation related to the target model

    setRecordRelation

    public void setRecordRelation(java.lang.String associationId,
                                  RecordRelation rr)
    Sets a RecordRelation related to the target model.

    Parameters:
    associationId - association id
    rr - RecordRelation related to the target model

    setProtectedFields

    protected void setProtectedFields(java.lang.String fields)
    Sets fields to be protected.

    Parameters:
    fields - A string of field names separated by comma.

    setExtraFields

    protected void setExtraFields(java.lang.String fields)
    Sets fields to be extra.

    Parameters:
    fields - A string of field names separated by comma.

    getValidationResults

    public ValidationResults getValidationResults()
    Returns the ValidationResults instance of this record.

    Returns:
    ValidationResults

    isValid

    public boolean isValid()
    Returns true if the record has no error.


    validatesRecord

    public void validatesRecord()

    Subclass must override this method in order to provide a meaningful validation.

    The default implementation of this method is empty.


    validatesRecordBeforeCreate

    public void validatesRecordBeforeCreate()
    This delegates to validatesRecord(). Subclass need to override this method in order to provide a meaningful validation.


    validatesRecordBeforeUpdate

    public void validatesRecordBeforeUpdate()
    This delegates to validatesRecord(). Subclass need to override this method in order to provide a meaningful validation.


    validatesRecordBeforeSave

    public void validatesRecordBeforeSave()
    This delegates to validatesRecord(). Subclass need to override this method in order to provide a meaningful validation.


    validatesRecordBeforeDelete

    public void validatesRecordBeforeDelete()
    The default implementation actually does nothing. Subclass need to override this method in order to provide a meaningful validation.


    getCalculator

    public Calculator getCalculator()

    Returns an instance of Calculations.

    Subclass must override this method if a different calculator is used.

    Returns:
    Calculations object

    validators

    public ModelValidators validators()

    Returns an instance of Validators.

    Subclass must override this method if a different validator is used.

    Returns:
    Validators object

    details

    public java.lang.String details()
    Shows details of the record. This method returns much more information than the toString() method, such as table name, dirty, existed in database, etc.

    Returns:
    String

    toString

    public java.lang.String toString()
    Returns a string representation of the record.

    Overrides:
    toString in class java.lang.Object
    Returns:
    String

    toMap

    public java.util.Map<java.lang.String,java.lang.Object> toMap()
    Returns a Map representation of the record. The keys in the map are column names in lowercase.

    Returns:
    Map

    toXML

    public java.lang.String toXML()
    Returns an XML representation of the object.
     Example:
     
       1234
       Scooter Rocks
       We love to use Scooter.
     
     

    Returns:
    xml string

    toJSON

    public java.lang.String toJSON()
    Returns a JSON representation of the object.

    Returns:
    a json string