A data model is declared using persistence.define
. The following two definitions define a Task
and Category
entity with a few simple properties. The property types are based on SQLite types, specifically supported types are (but any SQLite type is supported):
TEXT
: for textual dataINT
: for numeric valuesBOOL
: for boolean values (true
orfalse
)DATE
: for date/time value (with precision of 1 second)JSON
: a special type that can be used to store arbitrary JSON data. Note that this data can not be used to filter or sort in any sensible way. If internal changes are made to aJSON
property,persistence.js
may not register them. Therefore, a manual call toanObj.markDirty('jsonPropertyName')
is required before callingpersistence.flush
.
Example use:
var Task = persistence.define('Task', {
name: "TEXT",
description: "TEXT",
done: "BOOL"
});
var Category = persistence.define('Category', {
name: "TEXT",
metaData: "JSON"
});
var Tag = persistence.define('Tag', {
name: "TEXT"
});
The returned values are constructor functions and can be used to create new instances of these entities later.
It is possible to create indexes on one or more columns using EntityName.index
, for instance:
Task.index('done');
Task.index(['done', 'name']);
These indexes can also be used to impose unique constraints :
Task.index(['done', 'name'],{unique:true});
Relationships between entities are defined using the constructor function’s hasMany
call:
// This defines a one-to-many relationship:
Category.hasMany('tasks', Task, 'category');
// These two definitions define a many-to-many relationship
Task.hasMany('tags', Tag, 'tasks');
Tag.hasMany('tasks', Task, 'tags');
The first statement defines a tasks
relationship on category objects containing a QueryCollection
(see the section on query collections later) of Task
s, it also defines an inverse relationship on Task
objects with the name category
. The last two statements define a many-to-many relationships between Task
and Tag
. Task
gets a tags
property (a QueryCollection
) containing all its tags and vice versa, Tag
gets a tasks
property containing all of its tasks.
The defined entity definitions are synchronized (activated) with the database using a schemaSync
call, which takes a callback function (with a newly created transaction as an argument), that is called when the schema synchronization has completed, the callback is optional. Depending on your environment you call schemaSync
either on the persistence
(client-size use) or on your session
object (in server environments):
persistence.schemaSync();
// or, with a callback:
persistence.schemaSync(function(tx) {
// tx is the transaction object of the transaction that was
// automatically started
});
And using session
(in server environments):
session.schemaSync();
// or, with a callback:
session.schemaSync(function(tx) {
// tx is the transaction object of the transaction that was
// automatically started
});
There is also a migrations plugin you can check out, documentation can be found in persistence.migrations.docs.md
.
Mix-ins
You can also define mix-ins and apply them to entities of the model.
A mix-in definition is similar to an entity definition, except using defineMixin
rather than just define
. For example:
var Annotatable = persistence.defineMixin('Annotatable', {
lastAnnotated: "DATE"
});
You can define relationships between mix-in and entities. For example:
// A normal entity
var Note = persistence.define('Note', {
text: "TEXT"
});
// relationship between a mix-in and a normal entity
Annotatable.hasMany('notes', Note, 'annotated');
Once you have defined a mix-in, you can apply it to any entity of your model, with the Entity.is(mixin)
method. For example:
Project.is(Annotatable);
Task.is(Annotatable);
Now, your Project
and Task
entities have an additional lastAnnotated
property. They also have a one to many relationship called notes
to the Note
entity. And you can also traverse the reverse relationship from a Note
to its annotated
object.
Note that annotated
is a polymorphic relationship as it may yield either a Project
or a Task
(or any other entity which is `Annotatable’).
Note: Prefetch is not allowed (yet) on a relationship that targets a mixin. In the example above you cannot prefetch the annotated
relationship when querying the Note
entity.
Notes: this feature is very experimental at this stage. It needs more testing. Support for “is a” relationships (classical inheritance) is also in the works.