Mapping of Racket classes to database tables is performed using data-class, which extends a Racket class with expressions for mapping a database table and columns to the data class. Below is an example of a data-class with mapping expressions.
(define vehicle% (data-class object% (table-name "Vehicle") (column (vehicle-id #f "Vehicle_Id") (make #f "Make") (year 0 "Year") (axels 1 "Axels")) (primary-key vehicle-id) (join [owner customer% #:cardinality 'one-to-one (where (= (customer% id) (vehicle% customer-id)))]) (define/public (wheels) (* (get-column axels this) 2)) (super-new)))
Here a database table named "Vehicle" is mapped to the vehicle% data class. Columns are defined mapping the columns of the table to a field of the data class, as well as default value for the field. There is also an expression which defines the primary key. This table also has a join field owner which defines a one-to-one join to a customer% object.
data-class-clause = (table-name table-name external-name) | (init-column init-column-decl ...) | (column column-decl ...) | (join join-table-id join-decl ...) | (primary-key primary-key-decl auto-increment-kw) | class-clause | ... init-column-decl = (maybe-renamed column-name-decl) | (maybe-renamed default-value-expr column-name-decl) column-decl = (maybe-renamed default-value-expr column-name) maybe-renamed = id | (internal-id external-id) column-name-decl = column-name | (column-name external-name) join-decl = (join-name joined-table-id cardinality-kw where-clause) cardinality-kw =
| #:cardinality cardinality-expr primary-key-decl = column-id | (column-ids ...) auto-increment-kw =
| #:autoincrement auto-increment-expr
(or/c 'one-to-one 'one-to-many)
The table-name expression is a string that names the database table that the data class is mapped to. An optional external class name can also be defined. This external name is used when the class is exported to JSON or XML using the Racquel data class mixins.
The column and init-column are analogous to class field and init-field expressions. The difference being that columns are mapped to columns of a database and are persistent. A data class may also contain field columns, but the fields, as they are not mapped to database columns are not persisted.
Data classes can map joins to other data classes, using a join expression so that objects related to the object can be contained as part of the object. For example a join can be defined so that a field of the object can contain a list of order for a customer. The path of a join is defined using an RQL expression (see RQL: The Racquel Query Language) which allows for considerable flexibility in regard to what the contained objects are, e.g. a join could be defined so that only customer order in the last six months are contained in the object. The cardinality of the join is also definable using a keyword. Valid values for the cardinality keyword are 'one-to-one and 'one-to-many.
Joined objects are loaded lazily, that is, they are not loaded from the database until they are first referenced.
The primary-key expression defines the primary key for the mapped table. If a primary key consists of multiple parts then the columns must be defined in a list. An optional keyword #:autoincrement can be used to indicate that the primary key is an auto-incrementing a.k.a. identity column. Typically the value for this keyword is simply #t, however if the type of database being mapped to is PostgreSQL or Oracle, then the value of the keyword must be a string defining the name of the sequence entity being used for the table.
A data-class automatically defines a inspect with a value of #f, as class transparancy is necessary for persistent mechanism. Therefore defining an inspect expression will generate an error that an inspect expression has already been defined.
member-name-key? member-name-key? string? (listof (listof identifier? string? string?)) (listof (listof identifier? identifier? identifier? any/c)) (or/c identifier? (listof identifier?)) (or/c #t string? #f) (or/c string? #f) class : data-class?
class-id-key: the hidden name for the class’s metadata id field;
state-key: the hidden name for the class’s state field;
table-name: the database table name for the class;
columns: a list of column definition lists. Each column definition consists of the column field, the database column name, and the external name used for serialization;
joins: a list of join definition lists. Each join definition consists of the join field, the data class of the object(s) joined to, the cardinality (either 'one-to-one or 'one-to-many, and the RQL where-clause for the join;
primary-key: either an field or a list of fields that constitute the primary key;
autoincrement-key: set to #t if the primary key is an auto-increment key (unless the database system is PostgreSQL or Oracle, in which case it is the name of the sequence used for the primary key);
external-name: the external name used for JSON/XML serialization;