TypeORM 一对一关联篇:掌握实体关系与 JoinColumn

用户和身份证是一对一的关系,即一个用户对应一个身份证。

一对一是通过外键来存储这种关系的

创建数据库并初始化 TypeORM 项目

ts 复制代码
# 创建数据库
create database typeorm_one_to_one_relation_mapping;
​
# 初始化 TypeORM 项目
npx typeorm@latest init --name typeorm_one_to_one_relation_mapping --database mysql

修改数据库连接配置

具体参数配置可查看上一篇文章: TypeORM 基础篇:项目初始化与增删改查全流程

ts 复制代码
import "reflect-metadata"
import {DataSource} from "typeorm"
import {User} from "./entity/User"
​
export const AppDataSource = new DataSource({
  type: "mysql",
  host: "localhost",
  port: 3306,
  username: "root",
  password: "admin",
  database: "typeorm_one_to_one_relation_mapping",
  synchronize: true,
  logging: true,
  entities: [User],
  migrations: [],
  subscribers: [],
  poolSize: 10,
  connectorPackage: "mysql2",
  extra: {
    authPlugins: 'sha256_password'
  }
})
​

安装 mysql2 驱动包

bash 复制代码
npm i mysql2 --save

运行项目

bash 复制代码
npm run start

可以看到建表和插入数据的 sql 执行日志。


创建身份证表

创建 IdCard Entity

ts 复制代码
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm";
​
@Entity({
  name: "id_card"
})
export class IdCard {
  @PrimaryGeneratedColumn()
  id: number;
​
  @Column({
    length: 50,
    comment: "身份证号"
  })
  cardNumber: string;
}

在 DataSource 的 entities 中引入

ts 复制代码
import "reflect-metadata"
import {DataSource} from "typeorm"
import {User} from "./entity/User"
import {IdCard} from "./entity/IdCard";
​
export const AppDataSource = new DataSource({
  // ...
  entities: [User, IdCard],
  // ...
})
​

重新执行 npm run start 可以看到建表 sql


user 表和 IdCard 表建立一对一关联

IdCard 表中维护外键

在 IdCard Entity 中添加 user 列

  • @OneToOne() 指定它和 User 是一对一的关系
  • @JoinColum() 指定外键列在 IdCard 表中维护

重新执行 npm run start 可以看到日志:

设置外键级联关系

通过主表中如何访问到从表

如何在 user 表中访问 idCard 表?同样通过 @OneToOne 装饰器。

通过第二个参数告诉 typeorm,外键是另一个 Entity 的哪个属性。

查询主表带出从表数据

ts 复制代码
const users = await AppDataSource.manager.find(User, {
  relations: {
    idCard: true
  }
})
console.log(users)

查询结果:


增删改查

新增

ts 复制代码
import {AppDataSource} from "./data-source"
import {User} from "./entity/User"
import {IdCard} from "./entity/IdCard";
​
AppDataSource.initialize().then(async () => {
​
  const user = new User()
  user.firstName = "San"
  user.lastName = "Shi"
  user.age = 30
  await AppDataSource.manager.save(user)
​
  const idCard = new IdCard()
  idCard.cardNumber = "1234567890"
  idCard.user = user
​
  await AppDataSource.manager.save(user)
  await AppDataSource.manager.save(idCard)
​
}).catch(error => console.log(error))
  • 创建 user 和 idCard 对象
  • 设置 idCard.user 为 user,也就是建立关联关系

分别保存 user 和 idCard。

再次执行 npm run start。

查询数据库中可以看到输入插入成功

优化

上边先保存了 user 又保存了 idCard,能不能让它自动按照关联关系来保存呢?

可以通过 @OneToOne() 指定 cascade 为 true

cascade 用来告诉 typeorm 当增删改一个 Entity 时,是否级联增删改它关联的 Entity。

这样只需要保存 idCard 就可以了。


查询

在 find 方法中通过 relations 来声明关联查询,反之不进行关联查询。


修改

指定 id 就是修改,不指定 id 就是新增。


删除

因为前面设置的级联关系是 cascade,所以只要删除了 user,那关联的 idCard 就会跟着被删除。

ts 复制代码
const users = await AppDataSource.manager.find(User)
  console.log('删除前查询: ', users)
  await AppDataSource.manager.delete(User, 1)
  const usersAfterDelete = await AppDataSource.manager.find(User)
  console.log('删除后查询: ', usersAfterDelete)

执行日志

相关推荐
TDengine (老段)8 分钟前
从“数据堆场”到“智能底座”:TDengine IDMP如何统一数据语言
大数据·数据库·物联网·时序数据库·tdengine
l1t1 小时前
利用短整数类型和部分字符串优化DuckDB利用数组求解数独SQL
开发语言·数据库·sql·duckdb
一 乐1 小时前
医疗管理|医院医疗管理系统|基于springboot+vue医疗管理系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·医疗管理系统
TDengine (老段)2 小时前
从细胞工厂到智能制造:Extracellular 用 TDengine 打通数据生命线
java·大数据·数据库·科技·制造·时序数据库·tdengine
L.EscaRC4 小时前
浅析MySQL InnoDB存储引擎的MVCC实现原理
数据库·mysql
热爱运维的小七5 小时前
MongoDB 内存管理避坑指南:解决高占用、页错误等核心问题,让数据库性能翻倍
数据库·mongodb
冉冰学姐7 小时前
SSM公办小学网络报名系统f3d3p(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·ssm 框架·公办小学网络报名系统·教育信息化
叡鳍8 小时前
hive---HQL查询
数据库
vortex58 小时前
谷歌黑客语法挖掘 SQL 注入漏洞
android·数据库·sql
九河云9 小时前
软件开发平台 DevCloud
运维·服务器·数据库·科技·华为云