Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 723 lines (558 sloc) 27.435 kb
cd6c915 Simple prefetching works.
zef authored
1 persistence.js
2 ==============
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
3 `persistence.js` is a asynchronous Javascript object-relational
4 mapper library. It can be used both in the web browser and on
5 the server using [node.js](http://nodejs.org). It currently
6 supports 4 types of data stores:
7
8 * [HTML5 WebSQL database](http://dev.w3.org/html5/webdatabase/), a
9 somewhat controversial part of HTML5 that is supported in Webkit
10 browsers, specifically on mobile devices, including iPhone, Android
11 and Palm's WebOS.
12 * [Google Gears](http://gears.google.com), a browser plug-in that adds
13 a number of feature to the browser, including a in-browser database.
14 * [MySQL](http://www.mysql.com), using the
8e903cc @zefhemel Changed used mysql connector
zefhemel authored
15 [node-mysql](http://github.com/felixge/node-mysql), node.js module
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
16 on the server.
d6e3419 @zefhemel Updated in-memory store documentation and little fix.
zefhemel authored
17 * In-memory, as a fallback. Keeps the database in memory and is
18 cleaned upon a page refresh (or server restart), unless saved to
19 [localStorage](http://dev.w3.org/html5/webstorage/).
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
20
21 There is also an experimental support for [Qt 4.7 Declarative UI
22 framework
23 (QML)](http://doc.trolltech.org/4.7-snapshot/declarativeui.html) which
24 is an extension to JavaScript.
1b2c013 @zefhemel Documentation tweaks to accomodate for server environments.
zefhemel authored
25
26 For browser use, `persistence.js` has no dependencies on any other
27 frameworks, other than the Google Gears [initialization
28 script](http://code.google.com/apis/gears/gears_init.js), in case you
29 want to enable Gears support.
cd6c915 Simple prefetching works.
zef authored
30
3d5d3f0 @zefhemel Fixes to node blogging example, and description of plug-ins added to
zefhemel authored
31 Plug-ins
32 --------
33
34 There are a few `persistence.js` plug-ins available that add functionality:
35
36 * `persistence.search.js`, adds simple full-text search capabilities,
37 see `docs/search.md` for more information.
38 * `persistence.migrations.js`, supports data migrations (changes to
39 the database schema), see `docs/migrations.md` for more information.
40 * `persistence.sync.js`, supports database synchronization with a
41 remote server, see `docs/sync.md` for more information.
04897b2 @rsaccon more jquery integration documentation
rsaccon authored
42 * `jquery.persistence.js`, adds jQuery integration, including
43 jQuery-mobile ajax request interception and re-routing to persistencejs,
44 see `docs/jquery.md` for more information and `demo/jquerymobile` for a
45 simple demo.
3d5d3f0 @zefhemel Fixes to node blogging example, and description of plug-ins added to
zefhemel authored
46
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
47 A Brief Intro to Async Programming
48 ----------------------------------
bf2edb5 More info on asynchronous programming
Zef Hemel authored
49
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
50 In browsers, Javascript and the web page's rendering engine share
51 a single thread. The result of this is that only one thing can happen
52 at a time. If a database query would be performed _synchronously_,
53 like in many other programming environments like Java and PHP the
54 browser would freeze from the moment the query was issued until the
55 results came back. Therefore, many APIs in Javascript are defined as
56 _asynchronous_ APIs, which mean that they do not block when an
57 "expensive" computation is performed, but instead provide the call
58 with a function that will be invoked once the result is known. In the
59 meantime, the browser can perform other duties.
bf2edb5 More info on asynchronous programming
Zef Hemel authored
60
61 For instance, a synchronous database call call would look as follows:
62
63 var results = db.query("SELECT * FROM Table");
64 for(...) { ... }
65
66 The execution of the first statement could take half a second, during
67 which the browser doesn't do anything else. By contrast, the
68 asynchronous version looks as follows:
69
70 db.query("SELECT * FROM Table", function(results) {
71 for(...) { ... }
72 });
73
74 Note that there will be a delay between the `db.query` call and the
75 result being available and that while the database is processing the
76 query, the execution of the Javascript continues. To make this clear,
77 consider the following program:
78
79 db.query("SELECT * FROM Table", function(results) {
80 console.log("hello");
81 });
82 console.log("world");
83
84 Although one could assume this would print "hello", followed by
85 "world", the result will likely be that "world" is printed before
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
86 "hello", because "hello" is only printed when the results from the
bf2edb5 More info on asynchronous programming
Zef Hemel authored
87 query are available. This is a tricky thing about asynchronous
88 programming that a Javascript developer will have to get used to.
89
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
90 Using persistence.js in the browser
91 ===================================
92
14f8aac Working on the readme
Zef Hemel authored
93 Browser support
94 ---------------
95
96 * Modern webkit browsers (Google Chrome and Safari)
97 * Firefox (through Google Gears)
d6e3419 @zefhemel Updated in-memory store documentation and little fix.
zefhemel authored
98 * Opera
792501e @zefhemel Working on selectJSON, refactoring some code.
zefhemel authored
99 * Android browser (tested on 1.6 and 2.x)
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
100 * iPhone browser (iPhone OS 3+)
06e6304 Added WebOS to supported platforms.
Zef Hemel authored
101 * Palm WebOS (tested on 1.4.0)
d6e3419 @zefhemel Updated in-memory store documentation and little fix.
zefhemel authored
102 * Other browsers supporting `localStorage` (e.g. Firefox)
cd6c915 Simple prefetching works.
zef authored
103
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
104 (The following is being worked on:)
14f8aac Working on the readme
Zef Hemel authored
105 Internet Explorer is likely not supported (untested) because it
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
106 lacks `__defineGetter__` and `__defineSetter__` support, which
d6e3419 @zefhemel Updated in-memory store documentation and little fix.
zefhemel authored
107 `persistence.js` uses heavily. This may change in IE 9.
14f8aac Working on the readme
Zef Hemel authored
108
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
109 Setting up
110 ----------
111
112 To use `persistence.js` you need to clone the git repository:
113
114 git clone git://github.com/zefhemel/persistencejs.git
115
559e75c @zefhemel Doc update
zefhemel authored
116 To use it you need to copy `lib/persistence.js` to your web directory,
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
117 as well as any data stores you want to use. Note that the `mysql` and
118 `websql` stores both depend on the `sql` store. A typical setup
559e75c @zefhemel Doc update
zefhemel authored
119 requires you to copy at least `lib/persistence.js`,
120 `lib/persistence.store.sql.js` and `lib/persistence.store.websql.js` to your
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
121 web directory. You can then load them as follows:
122
123 <script src="persistence.js" type="application/javascript"></script>
124 <script src="persistence.store.sql.js" type="application/javascript"></script>
125 <script src="persistence.store.websql.js" type="application/javascript"></script>
126
d6e3419 @zefhemel Updated in-memory store documentation and little fix.
zefhemel authored
127 If you want to use the in-memory store (in combination with
128 `localStorage`) you also need the `persistence.store.memory.js`
129 included.
130
14f8aac Working on the readme
Zef Hemel authored
131
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
132 Setup your database
133 -------------------
cd6c915 Simple prefetching works.
zef authored
134
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
135 You need to explicitly configure the data store you want to use,
136 configuration of the data store is store-specific. The WebSQL store
137 (which includes Google Gears support) is configured as follows:
138
139 persistence.store.websql.config(persistence, 'yourdbname', 'A database description', 5 * 1024 * 1024);
140
141 The first argument is always supposed to be `persistence`. The second
142 in your database name (it will create it if it does not already exist,
143 the third is a description for you database, the last argument is the
144 maximum size of your database in bytes (5MB in this example).
145
9b06b0b @zefhemel Fix
zefhemel authored
146 The in-memory store
d6e3419 @zefhemel Updated in-memory store documentation and little fix.
zefhemel authored
147 ---------------------------------------
148
149 The in-memory store is offered as a fallback for browsers that do not
150 support any of the other supported stores (e.g. WebSQL or Gears). In
151 principal, it only keeps data in memory, which means that navigating
152 away from the page (including a reload or tab close) will result in
153 the loss of all data.
154
155 A way around this is using the `persistence.saveToLocalStorage` and
156 `persistence.loadFromLocalStorage` functions that can save the entire
157 database to the [localStorage](http://dev.w3.org/html5/webstorage/), which
158 is persisted indefinitely (similar to WebSQL).
159
160 If you're going to use the in-memory store, you can configure it as follows:
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
161
162 persistence.store.memory.config(persistence);
14f8aac Working on the readme
Zef Hemel authored
163
d6e3419 @zefhemel Updated in-memory store documentation and little fix.
zefhemel authored
164 Then, if desired, current data can be loaded from the localStorage using:
165
166 persistence.loadFromLocalStorage(function() {
167 alert("All data loaded!");
168 });
169
170 And saved using:
171
172 persistence.saveToLocalStorage(function() {
173 alert("All data saved!");
174 });
175
176 Drawbacks of the in-memory store:
177
178 * Performance: All actions that are typically performed by a database
179 (sorting, filtering), are now all performed in-memory using
180 Javascript.
181 * Limited database size: Loading and saving requires serialization of
182 all data from and to JSON, which gets more expensive as your dataset
183 grows. Most browsers have a maximum size of 5MB for `localStorage`.
184 * Synchronous behavior: Although the API is asynchronous, all
185 persistence actions will be performed synchronously on the main
186 Javascript thread, which may make the browser less responsive.
187
14f8aac Working on the readme
Zef Hemel authored
188 Schema definition
189 -----------------
190
191 A data model is declared using `persistence.define`. The following two
192 definitions define a `Task` and `Category` entity with a few simple
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
193 properties. The property types are based on [SQLite
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
194 types](http://www.sqlite.org/datatype3.html), specifically supported
195 types are (but any SQLite type is supported):
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
196
197 * `TEXT`: for textual data
198 * `INT`: for numeric values
199 * `BOOL`: for boolean values (`true` or `false`)
c65213f Added Fabio's Date type to documentation.
Zef Hemel authored
200 * `DATE`: for date/time value (with precision of 1 second)
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
201 * `JSON`: a special type that can be used to store arbitrary
202 [JSON](http://www.json.org) data. Note that this data can not be used
1e94adf Some more JSON property examples + minified version.
Zef Hemel authored
203 to filter or sort in any sensible way. If internal changes are made to a `JSON`
204 property, `persistence.js` may not register them. Therefore, a manual
205 call to `anObj.markDirty('jsonPropertyName')` is required before calling
206 `persistence.flush`.
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
207
208 Example use:
cd6c915 Simple prefetching works.
zef authored
209
73724ff Added .add and .remove methods to QueryCollections.
zef authored
210 var Task = persistence.define('Task', {
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
211 name: "TEXT",
212 description: "TEXT",
213 done: "BOOL"
cd6c915 Simple prefetching works.
zef authored
214 });
215
73724ff Added .add and .remove methods to QueryCollections.
zef authored
216 var Category = persistence.define('Category', {
1e94adf Some more JSON property examples + minified version.
Zef Hemel authored
217 name: "TEXT",
218 metaData: "JSON"
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
219 });
220
221 var Tag = persistence.define('Task', {
222 name: "TEXT"
cd6c915 Simple prefetching works.
zef authored
223 });
224
14f8aac Working on the readme
Zef Hemel authored
225 The returned values are constructor functions and can be used to
495d05e @zefhemel index support (see README)
zefhemel authored
226 create new instances of these entities later.
cd6c915 Simple prefetching works.
zef authored
227
495d05e @zefhemel index support (see README)
zefhemel authored
228 It is possible to create indexes on one or more columns using
229 `EntityName.index`, for instance:
230
231 Task.index('done');
bb7fe5b @sylvinus Unique index support
sylvinus authored
232 Task.index(['done', 'name']);
233
234 These indexes can also be used to impose unique constraints :
235
236 Task.index(['done', 'name'],{unique:true});
cd6c915 Simple prefetching works.
zef authored
237
14f8aac Working on the readme
Zef Hemel authored
238 Relationships between entities are defined using the constructor
239 function's `hasMany` call:
cd6c915 Simple prefetching works.
zef authored
240
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
241 // This defines a one-to-many relationship:
73724ff Added .add and .remove methods to QueryCollections.
zef authored
242 Category.hasMany('tasks', Task, 'category');
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
243 // These two definitions define a many-to-many relationship
244 Task.hasMany('tags', Tag, 'tasks');
245 Tag.hasMany('tasks', Task, 'tags');
cd6c915 Simple prefetching works.
zef authored
246
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
247 The first statement defines a `tasks` relationship on category objects
248 containing a `QueryCollection` (see the section on query collections
249 later) of `Task`s, it also defines an inverse relationship on `Task`
250 objects with the name `category`. The last two statements define a
251 many-to-many relationships between `Task` and `Tag`. `Task` gets a
252 `tags` property (a `QueryCollection`) containing all its tags and vice
253 versa, `Tag` gets a `tasks` property containing all of its tasks.
cd6c915 Simple prefetching works.
zef authored
254
14f8aac Working on the readme
Zef Hemel authored
255 The defined entity definitions are synchronized (activated) with the
256 database using a `persistence.schemaSync` call, which takes a callback
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
257 function (with a newly created transaction as an argument), that is called
14f8aac Working on the readme
Zef Hemel authored
258 when the schema synchronization has completed, the callback is
259 optional.
cd6c915 Simple prefetching works.
zef authored
260
261 persistence.schemaSync();
73724ff Added .add and .remove methods to QueryCollections.
zef authored
262 // or
14f8aac Working on the readme
Zef Hemel authored
263 persistence.schemaSync(function(tx) {
264 // tx is the transaction object of the transaction that was
265 // automatically started
266 });
cd6c915 Simple prefetching works.
zef authored
267
eae6f59 @fgrehm Finishing up documentation
fgrehm authored
268 There is also a migrations plugin you can check out, documentation can be found
58183c9 @fgrehm Fixing link to migrations documentation
fgrehm authored
269 in [persistence.migrations.docs.md](migrations/persistence.migrations.docs.md) file.
eae6f59 @fgrehm Finishing up documentation
fgrehm authored
270
71f97d7 first pass on mixins
Bruno Jouhier authored
271 Mix-ins
272 -------
273
274 You can also define mix-ins and apply them to entities of the model.
275
09d43e0 @zefhemel Documentation update
zefhemel authored
276 A mix-in definition is similar to an entity definition, except using
277 `defineMixin` rather than just `define`. For example:
71f97d7 first pass on mixins
Bruno Jouhier authored
278
b0353cb finished first pass on many to many support for mixins - basic tests …
Bruno Jouhier authored
279 var Annotatable = persistence.defineMixin('Annotatable', {
71f97d7 first pass on mixins
Bruno Jouhier authored
280 lastAnnotated: "DATE"
b0353cb finished first pass on many to many support for mixins - basic tests …
Bruno Jouhier authored
281 });
71f97d7 first pass on mixins
Bruno Jouhier authored
282
283 You can define relationships between mix-in and entities. For example:
284
285 // A normal entity
286 var Note = persistence.define('Note', {
287 text: "TEXT"
288 });
289
290 // relationship between a mix-in and a normal entity
291 Annotatable.hasMany('notes', Note, 'annotated');
292
293 Once you have defined a mix-in, you can apply it to any entity of your model,
294 with the `Entity.is(mixin)` method. For example:
295
b1ca96e fixed typo in readme
Bruno Jouhier authored
296 Project.is(Annotatable);
297 Task.is(Annotatable);
71f97d7 first pass on mixins
Bruno Jouhier authored
298
299 Now, your `Project` and `Task` entities have an additional `lastAnnotated` property.
300 They also have a one to many relationship called `notes` to the `Note` entity.
b0353cb finished first pass on many to many support for mixins - basic tests …
Bruno Jouhier authored
301 And you can also traverse the reverse relationship from a `Note` to its `annotated` object.
71f97d7 first pass on mixins
Bruno Jouhier authored
302
303 Note that `annotated` is a polymorphic relationship as it may yield either a `Project`
304 or a `Task` (or any other entity which is `Annotatable').
de89d62 documented the fact that prefetch is not allowed on mixins
Bruno Jouhier authored
305
b0353cb finished first pass on many to many support for mixins - basic tests …
Bruno Jouhier authored
306 Note: Prefetch is not allowed (yet) on a relationship that targets a mixin. In the example above
de89d62 documented the fact that prefetch is not allowed on mixins
Bruno Jouhier authored
307 you cannot prefetch the `annotated` relationship when querying the `Note` entity.
71f97d7 first pass on mixins
Bruno Jouhier authored
308
309 Notes: this feature is very experimental at this stage. It needs more testing.
8db0de9 @zefhemel Doc typo fix
zefhemel authored
310 Support for "is a" relationships (classical inheritance) is also in the works.
71f97d7 first pass on mixins
Bruno Jouhier authored
311
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
312 Creating and manipulating objects
313 ---------------------------------
314
315 New objects can be instantiated with the constructor functions.
316 Optionally, an object with initial property values can be passed as
317 well, or the properties may be set later:
318
319 var task = new Task();
320 var category = new Category({name: "My category"});
1e94adf Some more JSON property examples + minified version.
Zef Hemel authored
321 category.metaData = {rating: 5};
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
322 var tag = new Tag();
323 tag.name = "work";
324
325 Many-to-one relationships are accessed using their specified name, e.g.:
326 task.category = category;
327
328 One-to-many and many-to-many relationships are access and manipulated
329 through the `QueryCollection` API that will be discussed later:
330
331 task.tags.add(tag);
332 tasks.tags.remove(tag)l
333 tasks.tags.list(tx, function(allTags) { console.log(allTags); });
334
4941cd3 Added support for object removal (via `persistence.remove`).
Zef Hemel authored
335 Persisting/removing objects
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
336 ---------------------------
cd6c915 Simple prefetching works.
zef authored
337
14f8aac Working on the readme
Zef Hemel authored
338 Similar to [hibernate](http://www.hibernate.org), `persistence.js`
339 uses a tracking mechanism to determine which objects' changes have to
2f07855 @chetan51 Edited README.md via GitHub
chetan51 authored
340 be persisted to the database. All objects retrieved from the database
14f8aac Working on the readme
Zef Hemel authored
341 are automatically tracked for changes. New entities can be tracked to
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
342 be persisted using the `persistence.add` function:
cd6c915 Simple prefetching works.
zef authored
343
c37c40d Formatted readme slightly
Zef Hemel authored
344 var c = new Category({name: "Main category"});
345 persistence.add(c);
346 for ( var i = 0; i < 5; i++) {
347 var t = new Task();
348 t.name = 'Task ' + i;
349 t.done = i % 2 == 0;
350 t.category = c;
351 persistence.add(t);
352 }
cd6c915 Simple prefetching works.
zef authored
353
4941cd3 Added support for object removal (via `persistence.remove`).
Zef Hemel authored
354 Objects can also be removed from the database:
355
356 persistence.remove(c);
357
14f8aac Working on the readme
Zef Hemel authored
358 All changes made to tracked objects can be flushed to the database by
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
359 using `persistence.flush`, which takes a transaction object and
360 callback function as arguments. A new transaction can be started using
e38fbe0 Got rid of redundancy in readme.
Zef Hemel authored
361 `persistence.transaction`:
cd6c915 Simple prefetching works.
zef authored
362
363 persistence.transaction(function(tx) {
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
364 persistence.flush(tx, function() {
365 alert('Done flushing!');
366 });
367 });
14f8aac Working on the readme
Zef Hemel authored
368
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
369 For convenience, it is also possible to not specify a transaction or
370 callback, in that case a new transaction will be started
371 automatically. For instance:
14f8aac Working on the readme
Zef Hemel authored
372
373 persistence.flush();
374 // or, with callback
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
375 persistence.flush(function() {
14f8aac Working on the readme
Zef Hemel authored
376 alert('Done flushing');
377 });
378
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
379 Note that when no callback is defined, the flushing still happens
380 asynchronously.
14f8aac Working on the readme
Zef Hemel authored
381
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
382 __Important__: Changes and new objects will not be persisted until you
383 explicitly call `persistence.flush()`. The exception to this rule is
e38fbe0 Got rid of redundancy in readme.
Zef Hemel authored
384 using the `list(...)` method on a database `QueryCollection`, which also
385 flushes first, although this behavior may change in the future.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
386
d61084e persistence.sync.js now keeps track of changes to all entities in
Zef Hemel authored
387 Dumping and restoring data
792501e @zefhemel Working on selectJSON, refactoring some code.
zefhemel authored
388 --------------------------
389
390 The library supports two kinds of dumping and restoring data.
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
391
392 `persistence.dump` can be used to create an object containing a full
393 dump of a database. Naturally, it is adviced to only do this with
394 smaller databases. Example:
395
396 persistence.dump(tx, [Task, Category], function(dump) {
397 console.log(dump);
398 });
399
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
400 The `tx` is left out, a new transaction will be started for the
401 operation. If the second argument is left out, `dump` defaults
402 to dumping _all_ defined entities.
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
403
404 The dump format is:
405
406 {"entity-name": [list of instances],
407 ...}
408
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
409 `persistence.load` is used to restore the dump produced by
410 `persistence.dump`. Usage:
411
412 persistence.load(tx, dumpObj, function() {
413 alert('Dump restored!');
414 });
415
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
416 The `tx` argument can be left out to automatically start a new
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
417 transaction. Note that `persistence.load` does not empty the database
418 first, it simply attempts to add all objects to the database. If
419 objects with, e.g. the same ID already exist, this will fail.
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
420
d61084e persistence.sync.js now keeps track of changes to all entities in
Zef Hemel authored
421 Similarly, `persistence.loadFromJson` and `persistence.dumpToJson`
422 respectively load and dump all the database's data as JSON strings.
423
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
424 Entity constructor functions
425 ----------------------------
426
427 The constructor function returned by a `persistence.define` call
428 cannot only be used to instantiate new objects, it also has some
429 useful methods of its own:
430
431 * `EntityName.all([session])` returns a query collection containing
432 all
433 persisted instances of that object. The `session` argument is
434 optional and only required when `persistence.js` is used in
435 multi-session mode.
436 * `EntityName.load([session], [tx], id, callback)` loads an particular
437 object from the database by id or returns `null` if it has not been
438 found.
439 * `EntityName.findBy([session], [tx], property, value, callback)` searches
440 for a particular object based on a property value (this is assumed to
441 be unique), the callback function is called with the found object or
442 `null` if it has not been found.
bb7fe5b @sylvinus Unique index support
sylvinus authored
443 * `EntityName.index([col1, col2, ..., colN], options)` creates an index on a column
444 of a combination of columns, for faster searching. If options.unique is true,
445 the index will impose a unique constraint on the values of the columns.
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
446
447 And of course the methods to define relationships to other entities:
448
449 * `EntityName.hasMany(property, Entity, inverseProperty)` defines a
450 1:N or N:M relationship (depending on the inverse property)
451 * `EntityName.hasOne(property, Entity)` defines a 1:1 or N:1
452 relationship
453
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
454
455 Entity objects
456 --------------
457
458 Entity instances also have a few predefined properties and methods you
459 should be aware of:
460
461 * `obj.id`, contains the identifier of your entity, this is a
462 automatically generated (approximation of a) UUID. You should
463 never write to this property.
464 * `obj.fetch(prop, callback)`, if an object has a `hasOne`
465 relationship to another which has not yet been fetched from the
466 database (e.g. when `prefetch` wasn't used), you can fetch in manually
467 using `fetch`. When the property object is retrieved the callback function
468 is invoked with the result, the result is also cached in the entity
469 object itself.
470 * `obj.selectJSON([tx], propertySpec, callback)`, sometime you need to extract
4c18f83 @zefhemel Another README fix...
zefhemel authored
471 a subset of data from an entity. You for instance need to post a
472 JSON representation of your entity, but do not want to include all
473 properties. `selectJSON` allows you to do that. The `propertySpec`
474 arguments expects an array with property names. Some examples:
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
475 * `['id', 'name']`, will return an object with the id and name property of this entity
476 * `['*']`, will return an object with all the properties of this entity, not recursive
477 * `['project.name']`, will return an object with a project property which has a name
11dedaf @zefhemel README fixes
zefhemel authored
478 property containing the project name (hasOne relationship)
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
479 * `['project.[id, name]']`, will return an object with a project property which has an
11dedaf @zefhemel README fixes
zefhemel authored
480 id and name property containing the project name (hasOne relationship)
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
481 * `['tags.name']`, will return an object with an array `tags` property containing
11dedaf @zefhemel README fixes
zefhemel authored
482 objects each with a single property: name
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
483
484
14f8aac Working on the readme
Zef Hemel authored
485 Query collections
486 -----------------
487
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
488 A core concept of `persistence.js` is the `QueryCollection`. A
14f8aac Working on the readme
Zef Hemel authored
489 `QueryCollection` represents a (sometimes) virtual collection that can
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
490 be filtered, ordered or paginated. `QueryCollection`s are somewhate
491 inspired by [Google AppEngine's Query
492 class](http://code.google.com/appengine/docs/python/datastore/queryclass.html).
14f8aac Working on the readme
Zef Hemel authored
493 A `QueryCollection` has the following methods:
494
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
495 * `filter(property, operator, value)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
496 Returns a new `QueryCollection` that adds a filter, filtering a
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
497 certain property based on an operator and value. Supported operators
80824fe @zefhemel Introduced bug fixes, and new 'not in' operator.
zefhemel authored
498 are '=', '!=', '<', '<=', '>', '>=', 'in' and 'not in'. Example:
499 `.filter('done', '=', true)`
3843c74 @zefhemel Added or filters, usage (example in test/test.persistence.js):
zefhemel authored
500 * `or(filter)`
501 Returns a new `QueryCollection` that contains items either matching
502 the filters specified before calling `or`, or the filter represented
503 in the argument. The `filter` argument is of a `Filter` type, there
504 are three types of filters:
505 - `persistence.PropertyFilter`, which filters on properties (internally called when `filter(...)` is used.
506 Example: `new persistence.PropertyFilter('done', '=', true)`
507 - `persistence.AndFilter`, which is passed two filter objects as arguments, both of which should be true.
508 Example: `new persistence.AndFilter(new persistence.PropertyFilter('done', '=', true), new persistence.PropertyFilter('archived', '=', true))`
509 - `persistence.OrFilter`, which is passed two filter objects as arguments, one of which should be true.
510 Example: `new persistence.OrFilter(new persistence.PropertyFilter('done', '=', true), new persistence.PropertyFilter('archived', '=', true))`
511 * `and(filter)`
512 same as `or(filter)` except that both conditions should hold for items to be in the collection.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
513 * `order(property, ascending)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
514 Returns a new `QueryCollection` that will order its results by the
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
515 property specified in either an ascending (ascending === true) or
516 descending (ascending === false) order.
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
517 * `limit(n)`
518 Returns a new `QueryCollection` that limits the size of the result
519 set to `n` items. Useful for pagination.
520 * `skip(n)`
521 Returns a new `QueryCollection` that skips the first `n` results.
522 Useful for pagination.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
523 * `prefetch(rel)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
524 Returns a new `QueryCollection` that prefetches entities linked
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
525 through relationship `rel`, note that this only works for one-to-one
526 and many-to-one relationships.
a9fa189 @zefhemel Added `count` call to query collections. Fixed a little bug in
zefhemel authored
527 * `add(obj)`
528 Adds object `obj` to the collection.
529 * `remove(obj)`
530 Removes object `obj` from the collection.
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
531 * `list([tx], callback)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
532 Asynchronously fetches the results matching the formulated query.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
533 Once retrieved, the callback function is invoked with an array of
534 entity objects as argument.
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
535 * `each([tx], eachCallback)`
9520607 Basic implementation of LocalQueryCollection, only supports filtering
Zef Hemel authored
536 Asynchronously fetches the results matching the formulated query.
537 Once retrieved, the `eachCallback` function is invoked on each
538 element of the result objects.
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
539 * `forEach([tx], eachCallback)`
540 Alias for `each`
541 * `one([tx], callback)`
a2c07b5 @zefhemel Added `destroyAll` method to DbQueryCollections to remove all the items
zefhemel authored
542 Asynchronously fetches the first element of the collection, or `null` if none.
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
543 * `destroyAll([tx], callback)`
a2c07b5 @zefhemel Added `destroyAll` method to DbQueryCollections to remove all the items
zefhemel authored
544 Asynchronously removes all the items in the collection. __Important__: this does
545 not only remove the items from the collection, but removes the items themselves!
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
546 * `count([tx], callback)`
a9fa189 @zefhemel Added `count` call to query collections. Fixed a little bug in
zefhemel authored
547 Asynchronously counts the number of items in the collection. The arguments passed
548 to the `callback` function is the number of items.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
549
550 Query collections are returned by:
551
552 * `EntityName.all()`, e.g. `Task.all()`
553 * one-to-many and many-to-many relationships, e.g. `task.tags`
554
555 Example:
cd6c915 Simple prefetching works.
zef authored
556
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
557 var allTasks = Task.all().filter("done", '=', true).prefetch("category").order("name", false).limit(10);
cd6c915 Simple prefetching works.
zef authored
558
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
559 allTasks.list(null, function (results) {
560 results.forEach(function (r) {
561 console.log(r.name)
562 window.task = r;
cd6c915 Simple prefetching works.
zef authored
563 });
564 });
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
565
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
566 Using persistence.js on the server
567 ==================================
568
dd1c7c4 @zefhemel Set-up library to be used a node library installable via npm. In fact,
zefhemel authored
569 Installing `persistence.js` on node is easy using [npm](http://npmjs.org):
570
571 npm install persistencejs
572
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
573 Sadly the node.js server environment requires slight changes to
574 `persistence.js` to make it work with multiple database connections:
575
576 * A `Session` object needs to be passed as an extra argument to
577 certain method calls, typically as a first argument.
578 * Methods previously called on the `persistence` object itself are now
579 called on the `Session` object.
580
581 An example `node.js` application is included in `test/node-blog.js`.
582
583 Setup
584 -----
585 You need to `require` two modules, the `persistence.js` library itself
dd1c7c4 @zefhemel Set-up library to be used a node library installable via npm. In fact,
zefhemel authored
586 and the MySQL backend module.
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
587
dd1c7c4 @zefhemel Set-up library to be used a node library installable via npm. In fact,
zefhemel authored
588 var persistence = require('persistencejs/persistence').persistence;
589 var persistenceStore = require('persistencejs/persistence.store.mysql');
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
590
591 Then, you configure the database settings to use:
592
8d922e1 @zefhemel Added port argument to documentation as well
zefhemel authored
593 persistenceStore.config(persistence, 'localhost', 3306, 'dbname', 'username', 'password');
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
594
595 Subsequently, for every connection you handle (assuming you're
596 building a sever), you call the `persistenceStore.getSession()`
597 method:
598
b5c92f0 @zefhemel Fixed tiny mistake in README
zefhemel authored
599 var session = persistenceStore.getSession();
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
600
601 This session is what you pass around, typically together with a
602 transaction object. Note that currently you can only have one
603 transaction open per session and transactions cannot be nested.
604
605 session.transaction(function(tx) {
606 ...
607 });
608
96f2a57 documented commit/rollback feature
Bruno Jouhier authored
609 Commit and Rollback
610 -------------------
611
612 `persistence.js` works in autocommit mode by default.
613
614 You can override this behavior and enable explicit commit and rollback
615 by passing true as first argument to `persistence.transaction`.
616 You can then use the following two methods to control the transaction:
617
618 * `transaction.commit(session, callback)` commits the changes.
619 * `transaction.rollback(session, callback)` rollbacks the changes.
620
621 Typical code will look like:
622
623 session.transaction(true, function(tx) {
624 // create/update/delete objects
625 modifyThings(session, tx, function(err, result) {
626 if (err) {
627 // something went wrong
628 tx.rollback(session, function() {
629 console.log('changes have been rolled back: ' + ex.message);
630 });
631 }
632 else {
633 // success
634 tx.commit(session, function() {
635 console.log('changes have been committed: ' result);
636 });
637 });
638 });
639
640 Explicit commit and rollback is only supported on MySQL (server side)
641 for now.
642
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
643 Defining your data model
644 ------------------------
645
646 Defining your data model is done in exactly the same way as regular `persistence.js`:
647
648 var Task = persistence.define('Task', {
649 name: "TEXT",
650 description: "TEXT",
651 done: "BOOL"
652 });
653
654 A `schemaSync` is typically performed as follows:
655
656 session.schemaSync(tx, function() {
657 ...
658 });
659
660 Creating and manipulating objects
661 ---------------------------------
662
663 Creating and manipulating objects is done much the same way as with
664 regular `persistence.js`, except that in the entity's constructor you
665 need to reference the `Session` again:
666
667 var t = new Task(session);
668 ...
669 session.add(t);
670
671 session.flush(tx, function() {
672 ...
673 });
674
675 Query collections
b07a858 Moved issues to the issue tracker.
Zef Hemel authored
676 -----------------
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
677
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
678 Query collections work the same way as in regular `persistence.js`
679 with the exception of the `Entity.all()` method that now also requires
680 a `Session` to be passed to it:
681
682 Task.all(session).filter('done', '=', true).list(tx, function(tasks) {
683 ...
684 });
685
686 Closing the session
687 -------------------
688
689 After usage, you need to close your session:
690
691 session.close();
692
693 Bugs and Contributions
694 ======================
695
198de17 @zefhemel Moved the issue tracker to github, other bug tracker has too much down
zefhemel authored
696 If you find a bug, please [report
697 it](https://github.com/zefhemel/persistencejs/issues). or fork the
698 project, fix the problem and send me a pull request. For a list of
699 planned features and open issues, have a look at the [issue
700 tracker](https://github.com/zefhemel/persistencejs/issues).
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
701
0302c86 Added link to Google Group
Zef Hemel authored
702 For support and discussion, please join the [persistence.js Google
703 Group](http://groups.google.com/group/persistencejs).
704
0e32d43 @zefhemel Added AUTHORS file
zefhemel authored
705 Thanks goes to the people listed in `AUTHORS` for their contributions.
c65213f Added Fabio's Date type to documentation.
Zef Hemel authored
706
cda1de2 @zefhemel Added link to the persistence.js GWT wrapper.
zefhemel authored
707 If you use [GWT](http://code.google.com/webtoolkit/) (the Google Web
708 Toolkit), be sure to have a look at [Dennis Z. Jiang's GWT persistence.js
830419b @zefhemel Changed link to gwtmobile-persistence
zefhemel authored
709 wrapper](http://github.com/dennisjzh/GwtMobile-Persistence)
cda1de2 @zefhemel Added link to the persistence.js GWT wrapper.
zefhemel authored
710
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
711 License
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
712 =======
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
713
714 This work is licensed under the [MIT license](http://en.wikipedia.org/wiki/MIT_License).
cb16171 Added flattr link
Zef Hemel authored
715
716 Support this work
3d5d3f0 @zefhemel Fixes to node blogging example, and description of plug-ins added to
zefhemel authored
717 -----------------
cb16171 Added flattr link
Zef Hemel authored
718
719 You can support this project by flattering it:
720
721 <a href="http://flattr.com/thing/2510/persistence-js" target="_blank">
722 <img src="http://api.flattr.com/button/button-static-50x60.png" title="Flattr this" border="0" /></a>
Something went wrong with that request. Please try again.