mysql gour by,JugglingDB: JugglingDB 是一个跨数据库的 ORM 框架,提供了访问大多数数据库的通用接口,支持包括:mysql, mongodb, redis, ne...

jugglingdb.svg

jugglingdb.svg

jugglingdb.svg?style=shield

badge.svg?branch=master

About

JugglingDB is cross-db ORM for nodejs, providing

common interface to access most popular database formats. Currently

supported are: mysql, sqlite3, postgres, mongodb, redis and

js-memory-storage (yep, self-written engine for test-usage only). You can add

your favorite database adapter, checkout one of the existing adapters to learn

how.

Jugglingdb also works on client-side (using WebService and Memory adapters),

which allows to write rich client-side apps talking to server using JSON API.

Installation

npm install jugglingdb

and you should install appropriate adapter, for example for redis:

npm install jugglingdb-redis-hq

check following list of available adapters

JugglingDB adapters

Participation

Make sure all tests pass (npm test command)

Feel free to vote and comment on cards (tickets/issues), if you want to join team -- send me a message with your email.

If you want to create your own jugglingdb adapter, you should publish your

adapter package with name jugglingdb-ADAPTERNAME. Creating adapter is simple,

check jugglingdb/redis-adapter for example. JugglingDB core

exports common tests each adapter should pass, you could create your adapter in

TDD style, check that adapter pass all tests defined in test/common_test.js.

Usage

var Schema = require('jugglingdb').Schema;

var schema = new Schema('redis', {port: 6379}); //port number depends on your configuration

// define models

var Post = schema.define('Post', {

title: { type: String, length: 255 },

content: { type: Schema.Text },

date: { type: Date, default: function () { return new Date;} },

timestamp: { type: Number, default: Date.now },

published: { type: Boolean, default: false, index: true }

});

// simplier way to describe model

var User = schema.define('User', {

name: String,

bio: Schema.Text,

approved: Boolean,

joinedAt: Date,

age: Number

}, {

restPath: '/users' // tell WebService adapter which path use as API endpoint

});

var Group = schema.define('Group', {name: String});

// define any custom method

User.prototype.getNameAndAge = function () {

return this.name + ',' + this.age;

};

// models also accessible in schema:

schema.models.User;

schema.models.Post;

SEE schema(3) for details schema usage.

// setup relationships

User.hasMany(Post, {as: 'posts', foreignKey: 'userId'});

// creates instance methods:

// user.posts(conds)

// user.posts.build(data) // like new Post({userId: user.id});

// user.posts.create(data) // build and save

Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});

// creates instance methods:

// post.author(callback) -- getter when called with function

// post.author() -- sync getter when called without params

// post.author(user) -- setter when called with object

User.hasAndBelongsToMany('groups');

// user.groups(callback) - get groups of user

// user.groups.create(data, callback) - create new group and connect with user

// user.groups.add(group, callback) - connect existing group with user

// user.groups.remove(group, callback) - remove connection between group and user

schema.automigrate(); // required only for mysql and postgres NOTE: it will drop User and Post tables

// work with models:

var user = new User;

user.save(function (err) {

var post = user.posts.build({title: 'Hello world'});

post.save(console.log);

});

// or just call it as function (with the same result):

var user = User();

user.save(...);

// Common API methods

// each method returns promise, or may accept callback as last param

// just instantiate model

new Post({ published: 0, userId: 1 });

// save model (of course async)

Post.create();

// all posts

Post.all();

// all posts by user

Post.all({ where: { userId: user.id }, order: 'id', limit: 10, skip: 20 });

// the same as prev

user.posts(cb)

// get one latest post

Post.findOne({ where: { published: true }, order: 'date DESC' });

// same as new Post({userId: user.id});

user.posts.build({ published: 1 });

// save as Post.create({userId: user.id});

user.posts.create();

// find instance by id

User.find(1);

// find instance by id and reject promise when not found

User.fetch(1)

.then(user => console.log('found user', user))

.catch(err => console.error('can not fetch user with id 1:', err));

// count instances

User.count([conditions])

// destroy instance

user.destroy();

// destroy all instances

User.destroyAll();

// update multiple instances (currently only on the sql adapters)

Post.bulkUpdate({ update: { published: 0 }, where: { id: [1, 2, 3] }});

// update single instance

Post.update(1, { published: 1 });

SEE model(3) for more information about

jugglingdb Model API. Or man jugglingdb-model in terminal.

// Setup validations

User.validatesPresenceOf('name', 'email')

User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}});

User.validatesInclusionOf('gender', {in: ['male', 'female']});

User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']});

User.validatesNumericalityOf('age', {int: true});

User.validatesUniquenessOf('email', {message: 'email is not unique'});

user.isValid(function (valid) {

if (!valid) {

user.errors // hash of errors {attr: [errmessage, errmessage, ...], attr: ...}

}

})

SEE ALSO jugglingdb-validations(3) or

man jugglingdb-validations in terminal. Validation tests: ./test/validations.test.js

Hooks

The following hooks supported:

- afterInitialize

- beforeCreate

- afterCreate

- beforeSave

- afterSave

- beforeUpdate

- afterUpdate

- beforeDestroy

- afterDestroy

- beforeValidate

- afterValidate

Each callback is class method of the model, it should accept single argument: next, this is callback which should be called after end of the hook. Except afterInitialize because this method is syncronous (called after new Model).

During beforehooks the next callback accepts one argument, which is used to terminate flow. The argument passed on as the err parameter to the API method callback.

Object lifecycle:

var user = new User;

// afterInitialize

user.save(callback); // If Model.id isn't set, save will invoke Model.create() instead

// beforeValidate

// afterValidate

// beforeSave

// beforeUpdate

// afterUpdate

// afterSave

// callback

user.updateAttribute('email', 'email@example.com', callback);

// beforeValidate

// afterValidate

// beforeSave

// beforeUpdate

// afterUpdate

// afterSave

// callback

user.destroy(callback);

// beforeDestroy

// afterDestroy

// callback

User.create(data, callback);

// beforeValidate

// afterValidate

// beforeCreate

// beforeSave

// afterSave

// afterCreate

// callback

SEE jugglingdb-hooks or type this command

in your fav terminal: man jugglingdb-hooks. Also check tests for usage

examples: ./test/hooks.test.js

Your own database adapter

To use custom adapter, pass it's package name as first argument to Schema constructor:

var mySchema = new Schema('mycouch', {host:.., port:...});

In that case your adapter should be named as 'jugglingdb-mycouch' npm package.

Testing [outdated]

TODO: upd this section

Core of jugglingdb tests only basic features (database-agnostic) like

validations, hooks and runs db-specific tests using memory storage. It also

exports complete bucket of tests for external running. Each adapter should run

this bucket (example from jugglingdb-redis):

var jdb = require('jugglingdb'),

Schema = jdb.Schema,

test = jdb.test;

var schema = new Schema(__dirname + '/..', {host: 'localhost', database: 1});

test(module.exports, schema);

Each adapter could add specific tests to standart bucket:

test.it('should do something special', function (test) {

test.done();

});

Or it could tell core to skip some test from bucket:

test.skip('name of test case');

To run tests use this command:

npm test

Before running make sure you've installed package (npm install) and if you

running some specific adapter tests, ensure you've configured database

correctly (host, port, username, password).

Contributing

If you have found a bug please try to write unit test before reporting. Before

submit pull request make sure all tests still passed. Check

roadmap, github issues if you want to

help. Contribution to docs highly appreciated. Contents of man pages and

http://1602.github.com/jugglingdb/ generated from md files stored in this repo at ./docs repo

MIT License

Copyright (C) 2011 by Anatoliy Chakkaev

Permission is hereby granted, free of charge, to any person obtaining a copy

of this software and associated documentation files (the "Software"), to deal

in the Software without restriction, including without limitation the rights

to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

copies of the Software, and to permit persons to whom the Software is

furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in

all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

THE SOFTWARE.

trend.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ef-orm A Simple OR-Mapping framework on multiple databases. 使用手册(中文)http://geequery.github.io/ef-orm/manual/EF-ORM-user-guide.docx  使用示例工程 https://github.com/GeeQuery/ef-orm/tree/master/orm-tutorial EF-ORM一个轻量,便捷的Java ORM框架。并且具备若干企业级的应用特性,如分库分表、JTA事务等。 代码生成插件for eclipse(请在eclipse中Help/Install new software后输入地址并安装)http://geequery.github.io/plugins/1.3.x/特点一 EF的设计的一个主要目的是提高开发效率,减少编码工作,让开发者“零配置”“少编码”的操作数据库大部分功能。 例如:数据库查询条件的传入问题是所有ORM框架都不能回避的一个问题,所以我经常在想——既然我们可以用向DAO传入一个Entity来实现插入操作,为什么就不能用同样的方法来描述一个不以主键为条件的update/select/delete操作?为什么DAO的接口参数老是变来变去?为什么很多应用中,自行设计开发类来描述各种业务查询条件才能传入DAO?为什么我们不能在数据访问层上花费更少的时间和精力?   JPA1.0和早期的H框架,其思想是将关系型数据库抽象为对象池,这极大的限制了本来非常灵活的SQL语句的发挥空间。而本质上,当我们调用某H框架的session.get、session.load、session.delete时,我们是想传递一个以对象形式表达的数据库操作请求。只不过某H框架要求(并且限制)我们将其视作纯粹的“单个”对象而已。JPA 2.0为了弥补JPA1.0的不足,才将这种Query的思想引入为框架中的另一套查询体系——Criteria API。事实上针对单个对象的get/load/persist/save/update/merge/saveOrUpdate API和Criteria API本来就为一体,只不过是历史的原因被人为割裂成为两套数据库操作API罢了。   因此,对于关系型数据库而言——Entity和Query是一体两面的事物,所谓Query,可以包含各种复杂的查询条件,甚至可以作为一个完整的SQL操作请求的描述。为此,EF彻底将Entity和Query绑在了一起。这种思想,使得—— 开发人员需要编写的类更少。开发人员无需编写其他类来描述复杂的SQL查询条件。也无需编写代码将这些查询条件转换为SQL/HQL/JPQL。DAO层也不会有老要改来改去的接口和API,几乎可以做到零编码。 对单个对象进行CRUD的操作API现在和Criteria API合并在一起。Session对象可以直接提供原本要Criteria API才能提供实现的功能。API大大简化。 IQueryableEntity允许你将一个实体直接变化为一个查询(Query),在很多时候可以用来完成复杂条件下的数据查询。比如 ‘in (?,?,?)’, ‘Between 1 and 10’之类的条件。 xxQL有着拼装语句可读性差、编译器无法检查、变更维护困难等问题,但是却广受开发人员欢迎。这多少有历史原因,也有Criteria API设计上过于复杂的因素。两者一方是极端灵活但维护困难,一方是严谨强大而学习和编写繁琐,两边都是极端。事实上JPA的几种数据查询方式存在青黄不接的问题。选择查询语言xxQL,项目面临后续维护困难,数据库移植性差;选择Criteria API,代码臃肿,操作繁琐,很多人望而却步。EF的设计思想是使人早日摆脱拼装SQL/HQL/JPQL的困扰,而是用(更精简易用的)Criteria API来操作数据库。 基于轻量级Criteria API的操作方式,使得对数据库的变更和重构变得非常轻松,解决了SQL语句多对软件维护和移植造成产生的不利影响。 阅读推荐:第3、4章 特点二,将SQL的使用发挥到极致,解决SQL拼凑问题、数据库移植问题 大部分OLTP应用系统到最后都不免要使用SQL/JPQL,然而没有一个很好的方法解决SQL在多种数据库下兼容性的问题。 EF-ORM中采用了独特的SQL解析和改写技术,能够主动检查并确保SQL语句或者SQL片段在各个数据库上的兼容性。 EF中除了Criteria API以外,可以直接使用“SQL语句”或者“SQL片段”。但是这些SQL语句并不是直接传送给JDBC驱动的,而是 有着一个数据库方言层,经过方言层处理的SQL语句,就具备了在当前数据库上正确操作的能力。这相当于提供了一种能数据库操作的SQL语言。(E-SQL) E-SQL不但解决了异构数据库的语法问题、函数问题、特殊的写法问题,还解决了动态SQL问题、绑定变量扩展等特性。 对于各种常用SQL函数和运算符,都可以自动转换为当前数据库支持的方言来操作。其函数支持也要多于HQL支持的函数。 阅读推荐:第7、8章 特点三,可能是业界最快的ORM框架. 得益于ASM的动态代码生成技术,部分耗时操作通过动态代码固化为硬编码实现,EF-ORM的大部分操作性能要超过已知的其他框架。 实际性能测试表明,EF的大部分操作都要快于Hiberante和MyBatis, 部分操作速度甚至数十倍于上述框架。 EF在极限插入模式下,甚至刷新了每秒10万条写入的记录。远远超过了其他框架一个初步的性能测试:测试代码:http://geequery.github.io/ef-orm/manual/performance-test.rar 测试报告:http://geequery.github.io/ef-orm/manual/performance-compare.docx 阅读推荐:第9、17章 特点四,分库分表 开发过程中参照了Hibernate Shards、Alibaba TDDL、Cobar等框架,也是基于词法分析器来提取SQL参数,并计算路由。 能支持分库维度含糊等场景下的分库分表。以及包括多库多表下的 order by , distinct, group by, having等操作。 阅读推荐:第10章 特点五,常用DDL操作的封装 从数据库元数据访问,到建表,创建约束,创建sequence等各种DDL操作进行了封装,用户无需编写各种SQL,可以直接通过API操作数据库结构。 尤其是ALTER TABLE等修改数据库的语句,各种不同的RDBMS都有较大语法差异。特点六、解决各种RDBMS的移植问题 1、DML操作、自增值处理与返回、查询这些不同数据库操作差异很大的东西,都了统一的封装。 2、DDL操作、建表、删表、trunacte,Sequence创建和TABLE模拟Sequence等,都做了支持。 3、对SQL语法操作和函数的改写与支持。其他特性轻量 该框架对应用环境、连接池、 是否为J2EE应用等没有特殊要求。可以和EJB集成,也可与Spring集成,也可以单独使用。整个框架只有两个JAR包,模块和功能都较为轻量。依赖少 整个框架只有三个jar库。间接依赖仅有commons-lang, slf4j等7个通用库,作为一个ORM框架,对第三方依赖极小。简单直接的API 框架的API设计直接面向数据库操作,不绕弯子,开发者只需要数据库基本知识,不必学习大量新的操作概念即可使用API完成各种DDL/DML操作。 最大限度利用编译器减少编码错误的可能性 API设计和元数据模型(meta-model)的使用,使得常规的数据库查询都可以直接通过Criteria API来完成,无需使用任何JPQL/HQL/SQL。可以让避免用户犯一些语法、拼写等错误。JPA2规范兼容 使用JPA 2.0规范的标准注解方式来定义和操作对象。(但整个ORM不是完整的JPA兼容实现)更高的性能 依赖于ASM等静态字节码技术而不是CGlib,使得改善了代理性能;依赖于动态反射框架,内部数据处理上的开销几乎可以忽略。操作性能接近JDBC水平。对比某H开头的框架,在写入操作上大约领先30%,在大量数据读取上领先50%以上。更多的性能调优手段 debug模式下提供了大量性能日志,帮您分析性能瓶颈所在。同时每个查询都可以针对batch、fetchSize、maxResult、缓存、级联操作类型等进行调整和开关,可以将性能调到最优。可在主流数据库之间任意切换 支持Oracle、MySQL、Postgres、MSSQL、GBase、SQLite、HSQL、Derby等数据库。除了API方式下的操作能兼容各个数据库之外,就连SQL的本地化查询也能使之兼容。JMX动态调节 可以用JMX查看框架运行统计。框架的debug开关和其他参数都可以使用JMX动态调整。动态表支持 表结构元数据的API也向用户开放,同时支持在使用过程中,灵活调整映射关系,因此用户可以用API动态的创建表结构的模型,从而实现各种动态类型和表的映射(例如POJO中包含一个Map,用于映射各种动态扩展的字段)企业级特性支持 SQL分析,性能统计,分库分表,Oracle RAC支持,读写分离支持 标签:eform
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值