TypeORM - 查询构建器



查询构建器用于以简单的方式构建复杂的 SQL 查询。它从 Connection 方法和 QueryRunner 对象初始化。

我们可以通过三种方式创建 QueryBuilder。

连接

考虑一个使用连接方法使用 QueryBuilder 的简单示例。

import {getConnection} from "typeorm"; 

const user = await getConnection() .createQueryBuilder() 
.select("user") 
.from(User, "user") 
.where("user.id = :id", { id: 1 }) .getOne();

实体管理器

让我们如下创建使用实体管理器的查询构建器:

import {getManager} from "typeorm"; 

const user = await getManager() .createQueryBuilder(User, "user") .where("user.id = :id", { id: 1 })    .getOne();

Repository

我们可以使用 repository 创建查询构建器。如下所述:

import {getRepository} from "typeorm"; 

const user = await getRepository(User) .createQueryBuilder("user") .where("user.id = :id", { id: 1 }) .getOne();

别名

别名与 SQL 别名相同。我们使用 QueryBuilder 为 Student 表创建别名,如下所示:

import {getConnection} from "typeorm"; 

const user = await getConnection() .createQueryBuilder() 
.select("stud") 
.from(Student, "stud")

此查询等效于:

select * from students as stud

参数

参数 用作查询中动态值的占位符。在许多情况下,查找不同实体对象的查询将相同,除了值。例如,查找不同学生的查询相同,除了学生 ID 数据。在这种情况下,我们可以为学生 ID 使用参数,然后更改参数以获取不同的学生对象。

参数的另一个重要用途是防止 SQL 注入。它是现代 Web 应用程序中重要的安全漏洞之一。通过在查询中使用参数,我们可以避免 SQL 注入攻击。

参数的另一个重要用途是防止 SQL 注入。它是现代 Web 应用程序中重要的安全漏洞之一。通过在查询中使用参数,我们可以避免 SQL 注入攻击。

例如

"student.id = :id", { id: 1 }

这里,

:id - 参数名称。

{ id: 1 } - 参数的值

添加表达式

本节介绍如何使用表达式。

where

where 用于在条件匹配时过滤记录。

createQueryBuilder("student") .where("student.id = :id", { id: 1 })

此查询等效于:

select * from students student where student.id=1;

我们也可以在其中使用 AND、OR、NOT、IN 条件。

having

简单的 having 表达式定义如下:

createQueryBuilder("student") .having("student.id = :id", { id: 1 })

此查询等效于:

select * from students student having student.id=1;

orderBy

orderby 用于根据字段对记录进行排序。

createQueryBuilder("student") .orderBy("student.name")

此查询等效于:

select * from students student order by student.name;

groupBy

它用于根据指定的列对记录进行分组。

createQueryBuilder("student") .groupBy("student.id")

此查询等效于:

select * from students student group by student.id;

limit

它用于限制行的选择。下面,示例显示了如何在查询构建器中使用 limit:

createQueryBuilder("student") .limit(5)

此查询等效于:

select * from students student limit 5;

offset

Offset 用于指定跳过多少行结果。它定义如下:

createQueryBuilder("student") .offset(5)

此查询等效于:

select * from students student offset 5;

joins

join 子句用于根据相关列组合来自两个或多个表的行。考虑两个实体:

Student.ts

import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from "typeorm"; 
import {Project} from "./Project"; 

@Entity() 
export class User {
   
   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @OneToMany(type => Project, project => project.student) projects: project[]; 
}

Project.ts

import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm"; 
import {Student} from "./Student"; 

@Entity() 
export class Project { 

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   title: string; 
   
   @ManyToOne(type => Student, student => student.projects) student: Student; 
}

让我们使用以下查询执行简单的左连接:

const student = await createQueryBuilder("student") .leftJoinAndSelect("student.projects", "project") 
.where("student.name = :name", { name: "Student1" }) 
.getOne();

此查询等效于:

SELECT student.*, project.* FROM students student 
   LEFT JOIN projects project ON project.student = student.id 
   WHERE student.name = 'Student1'

类似地,我们也可以尝试内部连接。

不带选择的连接

我们可以不使用 select 连接数据。让我们使用内部连接尝试此示例,如下所示:

const student = await createQueryBuilder("student") .innerJoin("student.projects", "project") 
   .where("student.name = :name", { name: "student1" }) 
   .getOne();

以上查询等效于:

SELECT student.* FROM students student 
   INNER JOIN projects project ON project.student = student.id 
   WHERE student.name = 'Student1';

分页

如果您的应用程序中有更多数据,则需要分页、页面滑块或滚动功能。

例如,如果要显示应用程序中前五个学生的项目,

const students = await getRepository(Student) .createQueryBuilder("student") .leftJoinAndSelect("student.projects", "project") 
   .take(5) 
   .getMany();

子查询

称为另一个查询或嵌套查询中的查询。我们在 FROM、WHERE 和 JOIN 表达式中使用子查询。

简单的示例如下所示:

const projects = await connection .createQueryBuilder() .select("project.id", "id")
.addSelect(subQuery => { 
   return subQuery 
      .select("student.name", "name") .from(Student, "student") 
      .limit(1); 
}, "name")
.from(Project, "project") .getMany();

隐藏字段

如果您的任何列字段标记为 {select: false},则该列被视为隐藏列。考虑以下实体:

import {Entity, PrimaryGeneratedColumn, Column} from "typeorm"; 

@Entity() 
export class Student {

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @Column({select: false}) 
   address: string; 
}

这里,

address 字段标记为隐藏。我们可以使用addSelect 方法从列中检索信息。它定义如下:

const student = await connection.getRepository(Student) .createQueryBuilder() .select("student.id", "student")    .addSelect("student.address") .getMany();

getSql()

此方法用于获取查询构建器生成的 SQL 查询。它定义如下:

const sql = createQueryBuilder("student") .where("student.name = :name", { name: "Student1" })  .orWhere("student.age = :age", { age: 14 }) 
.getSql();
广告