Model declaration
Model declaration
Models are defined declaratively as classes.
import dorm.design;
// registers all Model derived classes in this module and publicly imported modules
mixin RegisterModels;
class User : Model
{
@maxLength(255) // Field is limited to 255 characters
string username;
@maxLength(255)
string password;
@maxLength(255)
Nullable!string email; // Nullable string field
ubyte age;
Nullable!DateTime birthday; // Nullable datetime field
}
will generate the following table (using MySQL syntax):
CREATE TABLE user (
id SERIAL,
username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
email VARCHAR(255),
age TINYINT UNSIGNED NOT NULL,
birthday DATETIME
);
Additional information
- the table name and column names are by default derived from the source code names (identifiers). They are converted into
snake_case
for all DB operations.- column names can be overriden using the
@columnName("...")
attribute.
- column names can be overriden using the
- to be a valid model, you need to define some
@primaryKey
or@Id
field.
Annotations
Annotation | Allowed on | Description |
---|---|---|
@autoCreateTime |
long or SysTime |
Sets the current time on creation of the model. More |
@autoUpdateTime |
long or SysTime |
Sets the current time on update of the model. More |
@choices(x) |
string or enum |
Sets a list of allowed values for the column. More |
@columnName(x) |
any | Overwrite the default generated column name. More |
@constructValue!(x) |
any | Set a constructed default value for the column. More |
@defaultValue(x) |
any | Set a constant default value for the column. More |
@defaultFromInit |
any | Set a constant default value for the column based on the default value on the D side. More |
@embedded |
structs |
Embed the annotated structs in the table. More |
@ignored |
any | Ignores the annotated field. More |
@index or @index(x) |
any | Create an index. More |
@maxLength(x) |
string or Nullable!string |
Set the maximum length of the VARCHAR type. More |
@primaryKey |
integer type or string |
Overwrite the default primary key. More |
@unique |
any except ManyToMany or OneToOne |
Enforce that the field value is unique throughout the column. More |
@validator!(x) |
any | Set a function to validate before any database operation More |
Auto Time fields
You can utilize the annotations autoCreateTime
and autoUpdateTime
to automatically set the current time on creation respectively on update
of the model to the annotated field.
Info
As SysTime
contains timezone information, dorm will also save it in the database.
class User : Model
{
@autoCreateTime
SysTime createdAt;
@autoUpdateTime
Nullable!SysTime updatedAt;
}
if you prefer using stdTime
instead of a SysTime field, you can just change the data type to long
:
Info
You don't need to set the @timestamp
annotation. @autoCreateTime
and
autoUpdateTime
implicitly also mean @timestamp
.
Datetime
When storing DateTime
, the value is taken and saved as-is to the database. When
using SysTime
, the value is first converted to UTC, then the timezone information
is stripped and then saved into the database. All stored datetimes are retrieved
back as UTC SysTime when queried.
Choices
With the @choices(x)
annotation, you can limit the possible values for this
field by specifying either the field type as a type of enum T : string
or
@choices("foo", "bar", "baz")
.
By utilizing enum
:
enum State: string
{
ok = "ok",
warn = "warn",
critical = "critical",
unknown = "unknown"
}
class User : Model
{
State state;
}
or by list of string
:
Info
You don't need to annotate this field with @maxLength(x)
as
VARCHAR
is not used as database type.
Column name
By setting the @columnName(x)
annotation, you can set the column name.
If you don't set this annotation, dorm will generate the column name for you.
x
must be of type string
.
Construct value
With the @constructValue!(x)
annotation, you can set the default value of the field,
if omitted on creation by calling a previous defined function.
x
is a function alias or lambda. The return value is assigned to the field on construction.
Caution
@constructValue!
functions are not serialized to the database, creating new rows
externally, will not populate them with the desired value.
import std.datetime.systime;
import std.datetime.datetime;
class User : Model
{
@constructValue!(() => Clock.currTime + 4.hours)
SysTime validUntil;
}
Default value
With the @defaultValue(x)
or @defaultFromInit
annotation, you can set the default value of the field,
if omitted on creation.
x
must be of the same data type as the field.
class User : Model
{
@maxLength(255)
@defaultValue("")
string comment;
/// Inherits DB default from User.init
@defaultFromInit
int counter = 1337;
}
Embedded
The @embedded
annotation can be used to embed the fields of the
embedded structs in the table of the current class.
Recursively embedding structs is also supported.
struct Person
{
@maxLength(255)
string firstName;
@maxLength(255)
string lastName;
}
class User : Model
{
@embedded
Person person;
}
This will create a table (using MySQL syntax):
CREATE TABLE user (
id SERIAL,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
);
Ignored
The @ignored
annotation will tell dorm to ignore the annotated field.
Indexes
The @index(x)
annotation can be used in multiple ways.
Without x
, an independent index is created.
To create composite indexes, specify x
as composite(y)
where y
is a string.
Info
If @embedded
is in use, composite(y)
can be also specified in the embedded struct.
To set the priority on a composite index, specify x
as priority(y)
,
where y
is an int
.
The lower the priority, the earlier the field appears in the definition of the index.
class User : Model
{
@index(composite("abc"), priority(2))
uint a;
@index(composite("abc"), priority(1))
uint b;
}
Info
If @priority(y)
is not specified, 10 is used as default.
On equal priorities, the field order is used to set the priorities.
Max Length
The @maxLength(x)
annotation can (and must) be set on string
data types.
As in most databases, VARCHAR
, which is used as data type representation for strings,
must have set the maximum length, you must set this annotation on all string
fields.
Primary Key
DORM adds an id
column as primary key by default to each model.
The @primaryKey
annotation is used to explicitly set the primary key.
The default id
field is not added in this case.
Timestamp
To save an long
as DATETIME
(UTC) in the database, you can set the
annotation @timestamp
. The value itself is interpreted as stdTime.
Info
You don't need to set this annotation if using @autoCreateTime
or @autoUpdateTime
as they set this implicit.
Unique
If @unique
is set, the value must be unique throughout the complete column.
Can be used on all field types except One2One and Many2Many fields.
Validator functions
Validator functions are triggered before inserting / updating any field in the database. Per field, you can have multiple validators. They are executed in order.
They must have the signature: (FieldType x) => bool
.