0

I'm trying to follow the lireddit tutorial and am getting stuck with the first mikro-orm migration.

I'm having the same problem as reported in this post.

I have modified the example entity constructor (although the same problem results from using the format provided in the mikro-orm docs).

Currently, I have a Posts.ts file with:

import { Entity, PrimaryKey, Property } from "@mikro-orm/core";
// import { v4 } from 'uuid';

@Entity()
export class Post {
  @PrimaryKey()
  id!: number;
  // uuid: string = v4();

  // @SerializedPrimaryKey()
  // id!: string;

  @Property({ type: "date" })
  createdAt: Date = new Date();

  @Property({ type: "date", onUpdate: () => new Date() })
  updatedAt: Date = new Date();

  @Property({ type: "text" })
  title!: string;
}

The code runs with:

const main = async () => {
  const orm = await MikroORM.init(config);
  await orm.getMigrator().up();
  const post = orm.em.create(Post, {title: "first title"});
  await orm.em.persistAndFlush(post);
};

main().catch((err) => {
    console.log(err);
});

The error message says:

NotNullConstraintViolationException: insert into "post" ("created_at", "title", "updated_at") values ('2021-08-18T22:13:54.599Z', 'first title', '2021-08-18T22:13:54.599Z') returning "id" - null value in column "_id" of relation "post" violates not-null constraint at PostgreSqlExceptionConverter.convertException

I don't know what this means or how to set a number on the id column. I note the mikro-orm docs define the primary key with an underscore prefix (also not sure what the underscore is doing) and also specify it as an ObjectId and then use the serialised primary key. I have tried using this format and get the same error.

I also tried:

  1. adding uuid as the primary key (instead of id) - shown in the commented code above, but I get the same error.

  2. adding a number as an id in the post const:

    const post = orm.em.create(Post, {title: "first title", id: 2});
    

This also generates a NotNullConstraintViolationException: error saying that id is null.

  1. one of the suggestions from this post is to add the following to the index.ts.

    const generator = orm.getSchemaGenerator();
    await generator.updateSchema();
    

I tried this and when I run yarn dev, the terminal just hangs at the start command (no errors are shown in the watch environment).

yarn run v1.22.11
$ nodemon dist/index.js
[nodemon] 2.0.12
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node dist/index.js`
  1. I removed those new two lines and tried again, this time with the initial flag on the mikro-orm migration:create command (after deleting my node modules folder, dist folder and src/migrations folder.

When I try that, it says

Error: Initial migration cannot be created, as some migrations already exist. The files listed are in the node modules folder.
  1. I also tried setting useTsNode to true in package.json - and get the same problems as described above.

Has anyone figured this out?

One thing I noticed is that after deleting the dist folder and node modules and re-running yarn, the dist/index.js file does not look like Ben's original. It now says:

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@mikro-orm/core");
const Post_1 = require("./entities/Post");
const mikro_orm_config_1 = __importDefault(require("./mikro-orm.config"));
const main = () => __awaiter(void 0, void 0, void 0, function* () {
    const orm = yield core_1.MikroORM.init(mikro_orm_config_1.default);
    yield orm.getMigrator().up();
    const post = orm.em.create(Post_1.Post, { title: "first title" });
    yield orm.em.persistAndFlush(post);
});
main().catch((err) => {
    console.log(err);
});
//# sourceMappingURL=index.js.map

I then try creating a new entity, called Posted (the same as Post, but for the name).

When I try creating that migration (which has to be new), I get an error that says:

TypeError: Cannot use 'in' operator to search for 'schema' in undefined

It then lists a number of files in the node_modules folder, as

at MetadataDiscovery.prepare node_modules/@mikro-orm/core/metadata/MetadataDiscovery.js:135:22)
at MetadataDiscovery.discoverReferences /@mikro-orm/core/metadata/MetadataDiscovery.js:125:48)
at MetadataDiscovery.findEntities node_modules/@mikro-orm/core/metadata/MetadataDiscovery.js:71:20)
at async MetadataDiscovery.discover /node_modules/@mikro-orm/core/metadata/MetadataDiscovery.js:34:9)
at async Function.init /node_modules/@mikro-orm/core/MikroORM.js:42:24)
Lauren Yim
  • 12,700
  • 2
  • 32
  • 59
Mel
  • 2,481
  • 26
  • 113
  • 273
  • 1
    Wipe your database and recreate the schema, this is not about your code, but about out of sync schema. You got the entity definition wrong when you ran it for the first time most probably, as you have both `id` and `_id` (you should not use serialized PK at all, that is for mongo only). PK diffing should be fixed in v5. – Martin Adámek Aug 20 '21 at 10:16
  • Thank you. I tried deleting the db entirely and made a new one. I get the same problem. – Mel Aug 21 '21 at 01:36
  • 1
    I doubt it, here in your entity definition there is no `_id` column, the ORM won't create one for you unless you define it, and the error you say is happening is exactly about such column. I would suggest to try some of the example projects. Ben's tutorial is full of misleading information. https://github.com/mikro-orm/mikro-orm-examples – Martin Adámek Aug 21 '21 at 09:27
  • If you want help with this one, publish it somewhere so I can review it as a whole, the information you provided here is not enough or not correct (e.g. the `_id` column, if the ORM creates it in the schema, your entity definition is not the one you say here). – Martin Adámek Aug 21 '21 at 09:30
  • Looking at the compiled main.js, you also most probably have TS target set to ES5 as it does use generators to mimic async/await. I doubt you want that, on the other hand I am not sure if it is causing any of this - maybe for the last one with `TypeError: Cannot use 'in' operator to search for 'schema' in undefined`. – Martin Adámek Aug 21 '21 at 09:39
  • thank you for the offer. My tsconfig is set to es6: "compilerOptions": { "target": "es6", "module": "commonjs", "lib": ["dom", "es6", "es2017", "esnext.asynciterable"], – Mel Aug 21 '21 at 23:51
  • I'll try working through your tutorials before I ask you to look at the repo. thank you very much for that kind offer. – Mel Aug 21 '21 at 23:52

2 Answers2

0

NotNullConstraintViolationException: insert into "post" ("created_at", "title", "updated_at") values ('2021-08-18T22:13:54.599Z', 'first title', '2021-08-18T22:13:54.599Z') returning "id" - null value in column "_id" of relation "post" violates not-null constraint at PostgreSqlExceptionConverter.convertException

This error is saying that your database has a column called "_id", and it's not nullable (there has to be a _id value), however you didn't provide it.

This issue indeed has to be fixed in your database. I recommend using a GUI management tool for DB. I use TablePlus.

Open up TablePlus, make a connection to your db, (provide username and password, set host to 127.0.0.1, setup a port number, specify which database you want to connect to) and then using the connection, inspect your database. There should be a column named _id. remove it, or rename it to id.

I think the reason why _id is created is because you used uppercase Id.

for example if you make a property named updatedAt in mikroorm then in database the column is called updated_at, not updatedAt, since sql is case insensitive. so if you named it Id then it would be _id in database

jeff pentagon
  • 796
  • 3
  • 12
-1

Seems MikoOrm needs the entity exported as a default:

@Entity()
class Post {
...
}

export default Post
soundslike
  • 393
  • 3
  • 12