Skip to main content

Introduction to Persistent Objects

This topic presents the concepts that are useful to understand when working with persistent classes.

Some of the examples shown here are from the Samples-Data sample (https://github.com/intersystems/Samples-DataOpens in a new tab). InterSystems recommends that you create a dedicated namespace called SAMPLES (for example) and load samples into that namespace. For the general process, see Downloading Samples for Use with InterSystems IRIS® data platform.

Persistent Classes

A persistent class is any class that inherits from %PersistentOpens in a new tab. A persistent object is an instance of such a class.

The %PersistentOpens in a new tab class is a subclass of %RegisteredObjectOpens in a new tab and thus is an object class. In addition to providing the object interface methods, the %PersistentOpens in a new tab class defines the persistence interface, a set of methods. Among other things, these methods enable you to save objects to the database, load objects from the database, delete objects, and test for existence.

Features Specific to Persistent Classes

Persistent classes can include several kinds of class members that are not meaningful in other types of classes:

  • Storage definitions, which govern access for the data for the class.

  • Indices. An index can define the unique identifier for objects in the class; see The Object ID.

    An index can also add a constraint that ensures uniqueness of a given field or combination of fields. For information on such indexes, see Defining Persistent Classes.

    Another purpose of an index is to define a specific sorted subset of commonly requested data associated with a class, so that queries can run more quickly. For example, as a general rule, if a query that includes a WHERE clause using a given field, the query runs more rapidly if that field is indexed. In contrast, if there is no index on that field, the engine must perform a full table scan, checking every row to see if it matches the given criteria — an expensive operation if the table is large. See Other Options for Persistent Classes.

  • Foreign keys, which establish referential integrity constraints between tables used when data is added or changed. If you use relationship properties, the system automatically treats these as foreign keys. But you can add foreign keys if you do not want to use relationships or if you have other reasons to add them.

    For more information on foreign keys, see Other Options for Persistent Classes.

  • Triggers, which define code to be executed automatically when specific events occur, specifically when a record is inserted, modified, or deleted.

    For more information on triggers, see Other Options for Persistent Classes.

Also note that a class method or a class query can be defined so that it can be invoked as a stored procedureOpens in a new tab, which enables you to invoke it from SQL.

Introduction to the Default SQL Projection

For any persistent class, the compiler generates an SQL table definition, so that the stored data can be accessed via SQL in addition to via the object interface.

The table contains one record for each saved object, and the table can be queried via InterSystems SQL. The following shows the results of a query of the Sample.Person table:

Table showing seven rows, and columns including ID, Age, DOB, Favorite Colors, Name, SSN, Spouse, Home City, and Home State.

The following table summarizes the default projection:

The Object-SQL Projection
From (Object Concept) ... To (Relational Concept) ...
Package Schema
Class Table
OID Identity field
Data type property Field
Reference property Reference field
Embedded object Set of fields
List property List field
Array property Child table
Stream property BLOB
Index Index
Class method Stored procedure

Other topics provide details and describe any changes you can make:

The Object ID

When you save an object for the first time, the system creates two permanent identifiers for it: the ID (discussed here) and the OID (discussed in the next section). You can use these identifiers later to access or remove the saved objects.

The object ID is the more commonly used identifier, and you use this ID as the first argument when you call methods such as %OpenId(), %ExistsId(), and %DeleteId(), available in all persistent classes.

Determining the ID

The system can automatically generate an integer to use as the ID. However, it is often useful to have an ID that is more meaningful to your application, so a common practice is to add an IdKey index definition to the persistent class, where this index refers to the property or properties that will provide the ID value. The following example includes an IdKey index that refers to the SSN property:

Class MyApp.Person Extends %Persistent
{

Index MainIDX On SSN [ Idkey ];

Property SSN As %String;

// other properties
}

In this example, the SSN for a person serves as the ID (and can be used with methods such as %OpenId(), %ExistsId(), and %DeleteId()). For example:

 set person=##class(MyApp.Person).%OpenId("123-45-6789")

When you add an IdKey index to a class, the compiler generates additional methods (known as index methods) for that class, which you can use to access or remove objects. The index methods include indexNameOpen(), indexNameExists(), and indexNameDelete(), where indexName is the name of the IdKey index. When the IdKey index refers to only a single property, these methods accept the value of that property as the first argument. For example:

 set person=##class(MyApp.Person).MainIDXOpen("123-45-6789")

You can have an IdKey index that refers to multiple properties, as follows:

Class MyApp.Account Extends %Persistent
{

Index MainIDX On (CountryCode,RegionalID) [ Idkey ];

Property CountryCode As %String;

Property RegionalID As %String;

// other properties
}

For such a class, the ID has a more complex form; it consists of the property values used by the IdKey index, concatenated with pairs of pipe || characters. In this case, it is simpler to use the generated index methods. The expected arguments are the property values used by the IdKey index, in the order used by that index. For example:

 set account=##class(MyApp.Account).MainIDXOpen("US","1234567")

Projection of Object IDs to SQL

The ID of an object is available in the corresponding SQL table. If possible, InterSystems IRIS uses the field name ID. InterSystems IRIS also provides a way to access the ID if you are not sure what field name to use. The system is as follows:

  • An object ID is not a property of the object and is treated differently from the properties.

  • If the class does not contain a property named ID (in any case variation), then the table also contains the field ID, and that field contains the object ID. For an example, see the previous section.

  • If the class contains a property that is projected to SQL with the name ID (in any case variation), then the table also contains the field ID1, and this field holds the value of the object ID.

    Similarly, if the class contains properties that are projected as ID and ID1, then the table also contains the field ID2, and this field holds the value of the object ID.

  • In all cases, the table also provides the pseudo-field %ID, which also holds the value of the object ID.

Object IDs in SQL

InterSystems IRIS enforces uniqueness for the ID field (whatever its actual name might be). InterSystems IRIS also prevents this field from being changed. This means that you cannot perform SQL UPDATE or INSERT operations on this field. For instance, the following shows the SQL needed to add a new record to a table:

INSERT INTO PERSON (FNAME, LNAME) VALUES (:fname, :lname)

Notice that this SQL does not refer to the ID field. InterSystems IRIS generates a value for the ID field and inserts that when it creates the requested record.

The Object OID

In addition to its ID, each saved object has an additional permanent identifier: its OID. The OID also includes the class name and is unique in the database.

The %PersistentOpens in a new tab class provides additional methods that use the OID; these include %Open(), %Exists(), and %Delete(). The methods that use OID as the argument do not include Id in their names; these methods are used much less often.

When a persistent object is stored in the database, the values of any of its reference attributes (that is, references to other persistent objects) are stored as OID values. For object attributes that do not have OIDs, the literal value of the object is stored along with the rest of the state of the object.

The OID is not available via SQL.

See Also

FeedbackOpens in a new tab