Entità Vista
Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →
Cos'è una ViewEntity?
Un'entità vista è una classe che mappa una vista del database.
Puoi creare un'entità vista definendo una nuova classe e contrassegnandola con @ViewEntity():
@ViewEntity() accetta le seguenti opzioni:
-
name- nome della vista. Se non specificato, il nome viene generato dal nome della classe dell'entità. -
database- nome del database nel server DB selezionato. -
schema- nome dello schema. -
expression- definizione della vista. Parametro obbligatorio. -
dependsOn- Elenco di altre viste da cui dipende la vista corrente. Se la tua vista utilizza un'altra vista nella sua definizione, puoi aggiungerla qui affinché le migrazioni vengano generate nell'ordine corretto.
expression può essere una stringa con colonne e tabelle correttamente escape, a seconda del database utilizzato (esempio PostgreSQL):
@ViewEntity({
expression: `
SELECT "post"."id" AS "id", "post"."name" AS "name", "category"."name" AS "categoryName"
FROM "post" "post"
LEFT JOIN "category" "category" ON "post"."categoryId" = "category"."id"
`
})
oppure un'istanza di QueryBuilder
@ViewEntity({
expression: (dataSource: DataSource) => dataSource
.createQueryBuilder()
.select("post.id", "id")
.addSelect("post.name", "name")
.addSelect("category.name", "categoryName")
.from(Post, "post")
.leftJoin(Category, "category", "category.id = post.categoryId")
})
Nota: il binding dei parametri non è supportato a causa di limitazioni dei driver. Utilizza invece parametri letterali.
@ViewEntity({
expression: (dataSource: DataSource) => dataSource
.createQueryBuilder()
.select("post.id", "id")
.addSelect("post.name", "name")
.addSelect("category.name", "categoryName")
.from(Post, "post")
.leftJoin(Category, "category", "category.id = post.categoryId")
.where("category.name = :name", { name: "Cars" }) // <-- this is wrong
.where("category.name = 'Cars'") // <-- and this is right
})
Ogni entità vista deve essere registrata nelle opzioni della tua data source:
import { DataSource } from "typeorm"
import { UserView } from "./entities/UserView"
const dataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: [UserView],
})
Colonne delle entità vista
Per mappare i dati dalla vista nelle colonne corrette dell'entità, devi contrassegnare le colonne dell'entità con il decoratore @ViewColumn()
e specificare queste colonne come alias nell'istruzione SELECT.
esempio con definizione stringa dell'espressione:
import { ViewEntity, ViewColumn } from "typeorm"
@ViewEntity({
expression: `
SELECT "post"."id" AS "id", "post"."name" AS "name", "category"."name" AS "categoryName"
FROM "post" "post"
LEFT JOIN "category" "category" ON "post"."categoryId" = "category"."id"
`,
})
export class PostCategory {
@ViewColumn()
id: number
@ViewColumn()
name: string
@ViewColumn()
categoryName: string
}
esempio con QueryBuilder:
import { ViewEntity, ViewColumn } from "typeorm"
@ViewEntity({
expression: (dataSource: DataSource) =>
dataSource
.createQueryBuilder()
.select("post.id", "id")
.addSelect("post.name", "name")
.addSelect("category.name", "categoryName")
.from(Post, "post")
.leftJoin(Category, "category", "category.id = post.categoryId"),
})
export class PostCategory {
@ViewColumn()
id: number
@ViewColumn()
name: string
@ViewColumn()
categoryName: string
}
Opzioni delle colonne vista
Le opzioni delle colonne vista definiscono opzioni aggiuntive per le colonne delle entità vista, simili alle opzioni delle colonne per le entità regolari.
Puoi specificare le opzioni delle colonne vista in @ViewColumn:
@ViewColumn({
name: "postName",
// ...
})
name: string;
Elenco delle opzioni disponibili in ViewColumnOptions:
-
name: string- Nome della colonna nella vista del database. -
transformer: { from(value: DatabaseType): EntityType, to(value: EntityType): DatabaseType }- Utilizzato per convertire proprietà di tipo arbitrarioDatabaseTypesupportato dal database in un tipoEntityType. Sono supportati anche array di transformer, applicati in ordine inverso durante la lettura. Nota: poiché le viste del database sono di sola lettura,transformer.to(value)non verrà mai utilizzato.
Indici per viste materializzate
È supportata la creazione di indici per viste materializzate se si utilizza PostgreSQL.
@ViewEntity({
materialized: true,
expression: (dataSource: DataSource) =>
dataSource
.createQueryBuilder()
.select("post.id", "id")
.addSelect("post.name", "name")
.addSelect("category.name", "categoryName")
.from(Post, "post")
.leftJoin(Category, "category", "category.id = post.categoryId"),
})
export class PostCategory {
@ViewColumn()
id: number
@Index()
@ViewColumn()
name: string
@Index("catname-idx")
@ViewColumn()
categoryName: string
}
Tuttavia, unique è attualmente l'unica opzione supportata per gli indici nelle viste materializzate. Le altre opzioni degli indici verranno ignorate.
@Index("name-idx", { unique: true })
@ViewColumn()
name: string
Esempio completo
Creiamo due entità e una vista contenente dati aggregati da queste entità:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
}
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToOne,
JoinColumn,
} from "typeorm"
import { Category } from "./Category"
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@Column()
categoryId: number
@ManyToOne(() => Category)
@JoinColumn({ name: "categoryId" })
category: Category
}
import { ViewEntity, ViewColumn, DataSource } from "typeorm"
@ViewEntity({
expression: (dataSource: DataSource) =>
dataSource
.createQueryBuilder()
.select("post.id", "id")
.addSelect("post.name", "name")
.addSelect("category.name", "categoryName")
.from(Post, "post")
.leftJoin(Category, "category", "category.id = post.categoryId"),
})
export class PostCategory {
@ViewColumn()
id: number
@ViewColumn()
name: string
@ViewColumn()
categoryName: string
}
poi popoliamo queste tabelle con dati e richiediamo tutti i dati dalla vista PostCategory:
import { Category } from "./entities/Category"
import { Post } from "./entities/Post"
import { PostCategory } from "./entities/PostCategory"
const category1 = new Category()
category1.name = "Cars"
await dataSource.manager.save(category1)
const category2 = new Category()
category2.name = "Airplanes"
await dataSource.manager.save(category2)
const post1 = new Post()
post1.name = "About BMW"
post1.categoryId = category1.id
await dataSource.manager.save(post1)
const post2 = new Post()
post2.name = "About Boeing"
post2.categoryId = category2.id
await dataSource.manager.save(post2)
const postCategories = await dataSource.manager.find(PostCategory)
const postCategory = await dataSource.manager.findOneBy(PostCategory, { id: 1 })
il risultato in postCategories sarà:
[ PostCategory { id: 1, name: 'About BMW', categoryName: 'Cars' },
PostCategory { id: 2, name: 'About Boeing', categoryName: 'Airplanes' } ]
e in postCategory:
PostCategory { id: 1, name: 'About BMW', categoryName: 'Cars' }