当前位置: 首页 > 软件库 > 数据库相关 > >

mikro-orm

授权协议 MIT License
开发语言 C/C++
所属分类 数据库相关
软件类型 开源软件
地区 不详
投 递 者 闻人嘉颖
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

MikroORM

TypeScript ORM for Node.js based on Data Mapper, Unit of Workand Identity Map patterns. Supports MongoDB, MySQL,MariaDB, PostgreSQL and SQLite databases.

Heavily inspired by Doctrine and Nextras Orm.

Build Status

�� Unit of What?

You might be asking: What the hell is Unit of Work and why should I care about it?

Unit of Work maintains a list of objects (entities) affected by a business transactionand coordinates the writing out of changes. (Martin Fowler)

Identity Map ensures that each object (entity) gets loaded only once by keeping everyloaded object in a map. Looks up objects using the map when referring to them.(Martin Fowler)

So what benefits does it bring to us?

Implicit Transactions

First and most important implication of having Unit of Work is that it allows handlingtransactions automatically.

When you call em.flush(), all computed changes are queried inside a databasetransaction (if supported by given driver). This means that you can control the boundariesof transactions simply by calling em.persistLater() and once all your changesare ready, calling flush() will run them inside a transaction.

You can also control the transaction boundaries manually via em.transactional(cb).

const user = await em.findOneOrFail(User, 1);
user.email = 'foo@bar.com';
const car = new Car();
user.cars.add(car);

// thanks to bi-directional cascading we only need to persist user entity
// flushing will create a transaction, insert new car and update user with new email
// as user entity is managed, calling flush() is enough
await em.flush();

ChangeSet based persistence

MikroORM allows you to implement your domain/business logic directly in the entities.To maintain always valid entities, you can use constructors to mark required properties.Let's define the User entity used in previous example:

@Entity()
export class User {

  @PrimaryKey()
  id!: number;

  @Property()
  name!: string;

  @OneToOne()
  address?: Address;

  @ManyToMany()
  cars = new Collection<Car>(this);

  constructor(name: string) {
    this.name = name;
  }

}

Now to create new instance of the User entity, we are forced to provide the name:

const user = new User('John Doe'); // name is required to create new user instance
user.address = new Address('10 Downing Street'); // address is optional

Once your entities are loaded, make a number of synchronous actions on your entities,then call em.flush(). This will trigger computing of change sets. Only entities(and properties) that were changed will generate database queries, if there are no changes,no transaction will be started.

const user = await em.findOneOrFail(User, 1, ['cars', 'address']);
user.title = 'Mr.';
user.address.street = '10 Downing Street'; // address is 1:1 relation of Address entity
user.cars.getItems().forEach(car => car.forSale = true); // cars is 1:m collection of Car entities
const car = new Car('VW');
user.cars.add(car);

// now we can flush all changes done to managed entities
await em.flush();

em.flush() will then execute these queries from the example above:

begin;
update user set title = 'Mr.' where id = 1;
update user_address set street = '10 Downing Street' where id = 123;
update car set for_sale = true where id = 1;
update car set for_sale = true where id = 2;
update car set for_sale = true where id = 3;
insert into car (brand, owner) values ('VW', 1);
commit;

Only One Instance of Entity

Thanks to Identity Map, you will always have only one instance of given entity in one context.This allows for some optimizations (skipping loading of already loaded entities), as well ascomparison by identity (ent1 === ent2).

�� Documentation

MikroORM v4 documentation, included in this repo in the root directory, is built withJekyll and publicly hosted on GitHub Pages at https://mikro-orm.io.

There is also auto-generated CHANGELOG.md file based on commit messages(via semantic-release).

You can browse MikroORM v3 docs at https://mikro-orm.io/docs/3.6/installation.

To upgrade to v4, please see the upgrading guide.

Core Features

�� Example Integrations

You can find example integrations for some popular frameworks in the mikro-orm-examples repository:

TypeScript Examples

JavaScript Examples

Articles

  • Introducing MikroORM, TypeScript data-mapper ORM with Identity Map
  • Handling transactions and concurrency in MikroORM
  • MikroORM 3: Knex.js, CLI, Schema Updates, Entity Generator and more…

�� Quick Start

First install the module via yarn or npm and do not forget to install the database driver as well:

Since v4, you should install the driver package, but not the db connector itself,e.g. install @mikro-orm/sqlite, but not sqlite3 as that is already includedin the driver package.

yarn add @mikro-orm/core @mikro-orm/mongodb     # for mongo
yarn add @mikro-orm/core @mikro-orm/mysql       # for mysql/mariadb
yarn add @mikro-orm/core @mikro-orm/mariadb     # for mysql/mariadb
yarn add @mikro-orm/core @mikro-orm/postgresql  # for postgresql
yarn add @mikro-orm/core @mikro-orm/sqlite      # for sqlite

or

npm i -s @mikro-orm/core @mikro-orm/mongodb     # for mongo
npm i -s @mikro-orm/core @mikro-orm/mysql       # for mysql/mariadb
npm i -s @mikro-orm/core @mikro-orm/mariadb     # for mysql/mariadb
npm i -s @mikro-orm/core @mikro-orm/postgresql  # for postgresql
npm i -s @mikro-orm/core @mikro-orm/sqlite      # for sqlite

Next you will need to enable support for decoratorsas well as esModuleInterop in tsconfig.json via:

"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,

Then call MikroORM.init as part of bootstrapping your app:

const orm = await MikroORM.init({
  entities: ['./dist/entities'], // path to your JS entities (dist), relative to `baseDir`
  dbName: 'my-db-name',
  type: 'mongo',
  clientUrl: '...', // defaults to 'mongodb://localhost:27017' for mongodb driver
});
console.log(orm.em); // access EntityManager via `em` property

There are more ways to configure your entities, take a look atinstallation page.

Read more about all the possible configuration options in Advanced Configuration section.

Then you will need to fork entity manager for each request so theiridentity maps will not collide.To do so, use the RequestContext helper:

const app = express();

app.use((req, res, next) => {
  RequestContext.create(orm.em, next);
});

You should register this middleware as the last one just before request handlers and beforeany of your custom middleware that is using the ORM. There might be issues when you registerit before request processing middleware like queryParser or bodyParser, so definitelyregister the context after them.

More info about RequestContext is described here.

Now you can start defining your entities (in one of the entities folders). This is howsimple entity can look like in mongo driver:

./entities/MongoBook.ts

@Entity()
export class MongoBook {

  @PrimaryKey()
  _id: ObjectID;

  @SerializedPrimaryKey()
  id: string;

  @Property()
  title: string;

  @ManyToOne()
  author: Author;

  @ManyToMany()
  tags = new Collection<BookTag>(this);

  constructor(title: string, author: Author) {
    this.title = title;
    this.author = author;
  }

}

For SQL drivers, you can use id: number PK:

./entities/SqlBook.ts

@Entity()
export class SqlBook {

  @PrimaryKey()
  id: number;

}

Or if you want to use UUID primary keys:

./entities/UuidBook.ts

import { v4 } from 'uuid';

@Entity()
export class UuidBook {

  @PrimaryKey()
  uuid = v4();

}

More information can be found indefining entities section in docs.

When you have your entities defined, you can start using ORM either via EntityManageror via EntityRepositorys.

To save entity state to database, you need to persist it. Persist takes care or decidingwhether to use insert or update and computes appropriate change-set. Entity referencesthat are not persisted yet (does not have identifier) will be cascade persisted automatically.

// use constructors in your entities for required parameters
const author = new Author('Jon Snow', 'snow@wall.st');
author.born = new Date();

const publisher = new Publisher('7K publisher');

const book1 = new Book('My Life on The Wall, part 1', author);
book1.publisher = publisher;
const book2 = new Book('My Life on The Wall, part 2', author);
book2.publisher = publisher;
const book3 = new Book('My Life on The Wall, part 3', author);
book3.publisher = publisher;

// just persist books, author and publisher will be automatically cascade persisted
await orm.em.persistAndFlush([book1, book2, book3]);

To fetch entities from database you can use find() and findOne() of EntityManager:

const authors = orm.em.find(Author, {});

for (const author of authors) {
  console.log(author); // instance of Author entity
  console.log(author.name); // Jon Snow

  for (const book of author.books) { // iterating books collection
    console.log(book); // instance of Book entity
    console.log(book.title); // My Life on The Wall, part 1/2/3
  }
}

More convenient way of fetching entities from database is by using EntityRepository, thatcarries the entity name so you do not have to pass it to every find and findOne calls:

const booksRepository = orm.em.getRepository(Book);

// with sorting, limit and offset parameters, populating author references
const books = await booksRepository.find({ author: '...' }, ['author'], { title: QueryOrder.DESC }, 2, 1);

// or with options object
const books = await booksRepository.find({ author: '...' }, { 
  populate: ['author'],
  limit: 1,
  offset: 2,
  orderBy: { title: QueryOrder.DESC },
});

console.log(books); // Book[]

Take a look at docs about working with EntityManageror using EntityRepository instead.

�� Contributing

Contributions, issues and feature requests are welcome. Please readCONTRIBUTING.mdfor details on the process for submitting pull requests to us.

Authors

�� Martin Adámek

See also the list of contributors who participated in this project.

Show Your Support

Please ⭐️ this repository if this project helped you!

�� License

Copyright © 2018 Martin Adámek.

This project is licensed under the MIT License - see the LICENSE file for details.

  • ORM::将数据表对象化。 最常用的四个字段: _db_group _belongs_to:和_has_many组合,可以实现表联接查询。(->with('modelalias')) _has_many _table_name   插入: $posts=ORM::factory('Posts'); $posts->user_id=4; $posts->label_id=1; $posts->tit

  • 对象关系映射(ORM)提供了概念性的、易于理解的模型化数据的方法。ORM方法论基于三个核心原则: 简单:以最基本的形式建模数据。 传达性:数据库结构被任何人都能理解的语言文档化。 精确性:基于数据模型创建正确标准化了的结构。 典型地,建模者通过收集来自那些熟悉应用程序但不熟练的数据建模者的人的信息开发信息模型。建模者必须能够用非技术企业专家可以理解的术语在概念层次上与数据结构进行通讯。建模者也必须

  • 原文网址: http://www.blogwind.com/Wuvist/56788.shtml Katze,是德文猫的意思,猫是很懒的……用Katze为偶这个“ORM”命名,是要强调其目的:少打代码。ORM加引号,是因为偶不认为它是真正的ORM,它只是个穿上ORM马甲的SqlHelper……它没有xml配置文件,默认映射类名为表名、属性名为列名。如果不一致,通过 Attribute修改。 Kat

  • 一、ORM简介          对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。那么,到底如何实现持久化呢?一种简单的方案是采用硬编码方式,为每一种可能的数据库访问操作提供单独的方法。         

  •   一、常见开源ORM框架     比喻:Kerosene ORM,DbLinq,Dapper,DynamicQuery,elinq,glinq,NPoco,Relinq,EF,ServiceStack.OrmLite,IQToolkit,对于这些框架,在单表查询这块支持的还蛮可以,但是对于多表查询的那种语法,我真有点接受不了,总感觉怪怪的,直观感觉就是没有了linq语法的那种美感,请忽视我的挑剔

 相关资料
  • 问题内容: 我正在创建一个Android应用,并且需要保留一个。我刚刚开始使用Realm ORM ,因为它支持一对一和一对多的枚举和列表。我还找到了解决字符串列表的方法(即,我必须创建一个封装字符串的StringWrapper类。但是,从文档中我了解,列表并不存在像这样的简单方法。因此,我正在寻找持久化地图的最佳方法。我目前的想法是用封装了(以前的地图关键字)和的对象列表替换我的地图。类似于。是否

  • 问题内容: 我在一个Android项目中使用ORMLite,并且我不想使用扩展活动,因为我是在AsyncTask上将值插入数据库中。 在文档中说: “如果您不想扩展和其他基类,那么您将需要复制它们的功能。您需要在代码的开头进行调用,保存帮助程序并根据需要使用它,然后在你完成了。” 它还说要在中添加数据库帮助程序类。所以我不确定我在做什么错。 我正在使用一个为我的数据层调用的类,如下所示: 我正在使

  • 问题内容: 我将RoboSpice与Spring for Android结合使用,并希望使用OrmLite保留对象的JSON数组。GSON用于JSON编组。使用默认缓存,一切都会按预期进行。但是OrmLite似乎不喜欢对象数组。 这是JSON的简化版本: 我想在以下对象中坚持这一点: 基于RoboSpice OrmLite示例,我创建了以下GsonSpringAndroidSpiceService

  • 问题内容: 我有以下表格- 对于这些表,关联的Dao和DaoImpl如下 数据库助手如下: 现在,当我尝试致电- 它错误并显示以下错误: 现在,如果我在A中没有foreign键-即如果A不包含 公共B b ,那么它可以正常工作。我在这里缺少什么吗? 提前非常感谢您。 问题答案: 我怀疑在异常堆栈跟踪的末尾有您丢失的原因消息。例如,如果我在上面重复了您的示例,则会得到: 因为有一个class的外部字

  • 问题内容: 如果我使用的是JPA2之类的ORM-我的实体已映射到数据库,那么我是否仍应使用DAO?似乎要增加很多开销。 例如,我将需要维护三个额外的程序包: 一个指定我的域对象的对象(它几乎映射了我的Entity对象): 一种包含指定我的DAO方法的接口 其中包含实现我的DAO的会话bean 现在,每当我需要执行新的CRUD操作时,都会增加很多额外的负担。 但是,从DAO中我看到的好处是: 您可以

  • 问题内容: 我在GoRM ORM中使用Go 。我有以下结构。关系很简单。一个城镇有多个地方,一个地方属于一个城镇。 现在,我想查询所有地方,并与他们所有的字段一起了解相应城镇的信息。这是我的代码: 我的样本数据库具有以下数据: 我 收到 这个: 但是我 希望 收到这样的信息(两个地方都属于同一个城镇): 我该如何查询?我尝试使用,并没有成功(可能是错误的方式)。我无法获得预期的结果。 问题答案: