Zum Hauptinhalt springen

Häufig gestellte Fragen

Inoffizielle Beta-Übersetzung

Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →

Wie aktualisiere ich ein Datenbankschema?

Eine Hauptaufgabe von TypeORM ist es, Ihre Datenbanktabellen mit Ihren Entitäten synchron zu halten. Dafür gibt es zwei Möglichkeiten:

  • Verwenden Sie synchronize: true in den DataSource-Optionen:

    import { DataSource } from "typeorm"

    const myDataSource = new DataSource({
    // ...
    synchronize: true,
    })

    Diese Option synchronisiert Ihre Datenbanktabellen automatisch mit den angegebenen Entitäten bei jeder Codeausführung.
    Während der Entwicklung ist dies ideal, in Produktionsumgebungen sollte die Option jedoch deaktiviert werden.

  • Verwenden Sie die Befehlszeilentools und führen Sie die Schema-Synchronisierung manuell aus:

    typeorm schema:sync

    Dieser Befehl führt die Schema-Synchronisierung durch.

Die Schema-Synchronisierung ist extrem schnell. Falls Sie überlegen, synchronize während der Entwicklung aus Leistungsgründen zu deaktivieren, testen Sie zuerst, wie schnell der Prozess tatsächlich ist.

Wie ändere ich einen Spaltennamen in der Datenbank?

Standardmäßig werden Spaltennamen aus Eigenschaftsnamen generiert. Sie können sie einfach ändern, indem Sie eine name-Option für die Spalte angeben:

@Column({ name: "is_active" })
isActive: boolean;

Wie setze ich einen Standardwert auf eine Funktion, z.B. NOW()?

Die default-Spaltenoption unterstützt Funktionen. Wenn Sie eine Funktion übergeben, die einen String zurückgibt, wird dieser String unverändert als Standardwert verwendet. Beispiel:

@Column({ default: () => "NOW()" })
date: Date;

Wie führe ich Validierungen durch?

Validierung ist nicht Teil von TypeORM, da es ein separater Prozess ist, der nicht direkt mit TypeORM zusammenhängt. Für Validierungen verwenden Sie class-validator - es funktioniert perfekt mit TypeORM.

Was bedeutet "Eigentümerseite" bei Relationen oder warum brauchen wir @JoinColumn und @JoinTable?

Beginnen wir mit einer one-to-one-Beziehung. Angenommen wir haben zwei Entitäten: User und Photo:

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number

@Column()
name: string

@OneToOne()
photo: Photo
}
@Entity()
export class Photo {
@PrimaryGeneratedColumn()
id: number

@Column()
url: string

@OneToOne()
user: User
}

Dieses Beispiel enthält kein @JoinColumn, was falsch ist. Warum? Für eine echte Relation müssen wir eine Spalte in der Datenbank anlegen. Wir benötigen entweder eine userId-Spalte in photo oder photoId in user. Doch welche Spalte soll angelegt werden - userId oder photoId? TypeORM kann das nicht für Sie entscheiden. Für diese Entscheidung müssen Sie @JoinColumn auf einer Seite verwenden. Wenn Sie @JoinColumn in Photo setzen, wird eine userId-Spalte in der photo-Tabelle erstellt. Wenn Sie @JoinColumn in User setzen, entsteht eine photoId-Spalte in der user-Tabelle. Die Seite mit @JoinColumn wird "Eigentümerseite der Beziehung" genannt. Die andere Seite ohne @JoinColumn heißt "inverse Seite (Nicht-Eigentümerseite) der Beziehung".

Bei einer @ManyToMany-Relation gilt dasselbe. Hier zeigt @JoinTable die Eigentümerseite an.

Bei @ManyToOne oder @OneToMany ist @JoinColumn nicht nötig, weil diese Decorators unterschiedlich sind und die Tabelle mit dem @ManyToOne-Decorator automatisch die Relationsspalte erhält.

Die Decorators @JoinColumn und @JoinTable können auch verwendet werden, um zusätzliche Einstellungen wie Spaltennamen oder Verbindungstabellennamen zu definieren.

Wie füge ich zusätzliche Spalten in eine Many-to-Many (Verbindungs-)Tabelle ein?

Zusätzliche Spalten in einer automatisch erstellten Many-to-Many-Tabelle sind nicht möglich. Erstellen Sie stattdessen eine separate Entität, verknüpfen Sie sie über zwei Many-to-One-Beziehungen mit den Zielentitäten (der Effekt entspricht einer Many-to-Many-Tabelle) und fügen Sie dort zusätzliche Spalten hinzu. Details finden Sie unter Many-to-Many-Beziehungen.

Wie gehe ich mit der TypeScript-Compiler-Option outDir um?

Wenn Sie die Compiler-Option outDir verwenden, vergessen Sie nicht, die von Ihrer App genutzten Assets und Ressourcen in das Ausgabeverzeichnis zu kopieren.
Alternativ stellen Sie sicher, dass die Pfade zu diesen Assets korrekt konfiguriert sind.

Wichtig zu wissen: Wenn Sie Entitäten löschen oder verschieben, bleiben die alten Entitäten im Ausgabeverzeichnis erhalten.
Beispiel: Sie erstellen eine Post-Entität und benennen sie in Blog um.
Obwohl Post.ts nicht mehr in Ihrem Projekt existiert, bleibt Post.js im Ausgabeverzeichnis.
TypeORM liest dann beide Entitäten – Post und Blog – was zu Fehlern führen kann.
Daher wird dringend empfohlen, bei Änderungen an Entitäten mit aktivierter outDir-Option:

  1. Das Ausgabeverzeichnis zu löschen
  2. Das Projekt neu zu kompilieren

Wie verwende ich TypeORM mit ts-node?

Durch ts-node entfällt das wiederholte Kompilieren.
Bei Nutzung von ts-node geben Sie ts-Entitäten in den DataSource-Optionen an:

{
entities: [__dirname + "/entities/**/*{.js,.ts}"],
subscribers: [__dirname + "/subscribers/**/*{.js,.ts}"]
}

Falls JavaScript-Dateien in dasselbe Verzeichnis wie TypeScript-Dateien kompiliert werden,
verwenden Sie die outDir-Compiler-Option, um
dieses Problem zu vermeiden.

Für die CLI-Nutzung mit ts-node führen Sie TypeORM so aus:

npx typeorm-ts-node-commonjs schema:sync

Für ESM-Projekte verwenden Sie stattdessen:

npx typeorm-ts-node-esm schema:sync

Wie verwende ich Webpack für das Backend?

Wie verwende ich Webpack für das Backend?

const FilterWarningsPlugin = require('webpack-filter-warnings-plugin');

module.exports = {
...
plugins: [
// ignore the drivers you don't want. This is the complete list of all drivers -- remove the suppressions for drivers you want to use.
new FilterWarningsPlugin({
exclude: [/mongodb/, /mssql/, /mysql2/, /oracledb/, /pg/, /pg-native/, /pg-query-stream/, /react-native-sqlite-storage/, /redis/, /sqlite3/, /sql.js/, /typeorm-aurora-data-api-driver/]
})
]
};

Migrationen bündeln

Standardmäßig versucht Webpack, alles in einer Datei zu bündeln. Dies kann problematisch sein, wenn Ihr Projekt Migrationsdateien enthält, die nach dem Deployment des gebündelten Codes in der Produktion ausgeführt werden sollen. Um sicherzustellen, dass alle Ihre Migrationen von TypeORM erkannt und ausgeführt werden können, sollten Sie für die Migrationsdateien die "Object Syntax" in der entry-Konfiguration verwenden.

const { globSync } = require("node:fs")
const path = require("node:path")

module.exports = {
// ... your webpack configurations here...
// Dynamically generate a `{ [name]: sourceFileName }` map for the `entry` option
// change `src/db/migrations` to the relative path to your migrations folder
entry: globSync(path.resolve("src/db/migrations/*.ts")).reduce(
(entries, filename) => {
const migrationName = path.basename(filename, ".ts")
return Object.assign({}, entries, {
[migrationName]: filename,
})
},
{},
),
resolve: {
// assuming all your migration files are written in TypeScript
extensions: [".ts"],
},
output: {
// change `path` to where you want to put transpiled migration files.
path: __dirname + "/dist/db/migrations",
// this is important - we want UMD (Universal Module Definition) for migration files.
libraryTarget: "umd",
filename: "[name].js",
},
}

Zudem optimiert Webpack ab Version 4 bei mode: 'production' Dateien standardmäßig – inklusive Code-Mangling zur Dateigrößenreduzierung. Dies beeinträchtigt die Migrationen, da TypeORM auf deren Namen angewiesen ist, um bereits ausgeführte Migrationen zu identifizieren. Sie können die Minimierung komplett deaktivieren, indem Sie folgendes hinzufügen:

module.exports = {
// ... other Webpack configurations here
optimization: {
minimize: false,
},
}

Alternativ können Sie, wenn Sie den UglifyJsPlugin verwenden, ihn so konfigurieren, dass Klassen- oder Funktionsnamen nicht geändert werden:

const UglifyJsPlugin = require("uglifyjs-webpack-plugin")

module.exports = {
// ... other Webpack configurations here
optimization: {
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
keep_classnames: true,
keep_fnames: true,
},
}),
],
},
}

Stellen Sie sicher, dass transpilierte Migrationsdateien in den DataSource-Optionen eingebunden sind:

// TypeORM Configurations
module.exports = {
// ...
migrations: [__dirname + "/migrations/**/*{.js,.ts}"],
}

Wie verwendet man TypeORM in ESM-Projekten?

Fügen Sie "type": "module" in die package.json Ihres Projekts ein, damit TypeORM import( ... ) für Dateien verwendet.

Um Import-Probleme durch zirkuläre Abhängigkeiten zu vermeiden, verwenden Sie den Relation-Wrapper-Typ für Relationstyp-Definitionen in Entitäten:

@Entity()
export class User {
@OneToOne(() => Profile, (profile) => profile.user)
profile: Relation<Profile>
}

Dies verhindert, dass der Eigenschaftstyp im transpilierten Code in den Eigenschafts-Metadaten gespeichert wird, was zirkuläre Abhängigkeitsprobleme verhindert.

Da der Spaltentyp bereits durch den @OneToOne-Decorator definiert ist, entfällt die Notwendigkeit zusätzlicher Typ-Metadaten, die TypeScript speichert.

Wichtig: Verwenden Sie Relation nicht bei Nicht-Relations-Spaltentypen