TypeORM:主列的默认值
TypeORM: Default values for primary column
尝试使用 TypeORM(在 NestJs 中)将实体保存到具有默认值的主列的数据库时遇到问题。
TL;DR 当 default
似乎什么都没做时,你究竟如何使用 TypeORM 设置默认列值?
编辑 1:好的,所以 default
似乎是数据库级别,之前有点错过了,但仍然 @BeforeInsert()
应该可以解决问题(但还没有)。
编辑 2:显然 @BeforeInsert()
挂钩有效,但前提是 .save()
是用 .save(new UserSession(userId))
而不是 .save({ userId: userId })
调用的(这当然需要适当的构造函数UserSession
).
设置
我有实体 UserSession
,注意 sessionId
字段,它的默认值应该是 cryptoRandomString({ length: 128, type: 'alphanumeric' })
returns.
@Entity('user_session')
export class UserSession {
@PrimaryColumn({
name: 'session_id',
default: () => cryptoRandomString({ length: 128, type: 'alphanumeric' })
})
sessionId: string
@Column({
name: 'user_id',
})
userId: string
}
然后我使用 TypeORM 存储库 .save()
函数将对象写入数据库,如下所示:
@Injectable()
export class AuthService {
constructor(
@InjectRepository(UserSession)
private readonly userSessionRepository: Repository<UserSession>
) {}
async createNewSession(userId: string): Promise<void> {
// Create new session
const session = await this.userSessionRepository.save({
userId: userId
})
// If only it got that far...
}
}
错误
在这一点上,如果没有设置 'manually',我希望 TypeORM 为 sessionId
设置一个默认值。但是,它只是抛出一个错误:
[Nest] 23088 - 04/06/2021, 23:18:44 [ExceptionsHandler] ER_NO_DEFAULT_FOR_FIELD: Field 'session_id' doesn't have a default value +4032ms
QueryFailedError: ER_NO_DEFAULT_FOR_FIELD: Field 'session_id' doesn't have a default value
at new QueryFailedError (E:\SAC\projects\api-flexrent\node_modules\typeorm\error\QueryFailedError.js:12:28)
at Query.<anonymous> (E:\SAC\projects\api-flexrent\node_modules\typeorm\driver\mysql\MysqlQueryRunner.js:217:45)
at Query.<anonymous> (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\Connection.js:526:10)
at Query._callback (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\Connection.js:488:16)
at Query.Sequence.end (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
at Query.ErrorPacket (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\sequences\Query.js:92:8)
at Protocol._parsePacket (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\Protocol.js:291:23)
at Parser._parsePacket (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\Parser.js:433:10)
at Parser.write (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\Parser.js:43:10)
at Protocol.write (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\Protocol.js:38:16)
绝望
在旧 google 上花了一些时间后,我尝试了几种变体,但都不起作用(并抛出相同的错误):
@PrimaryColumn({
name: 'session_id',
default: cryptoRandomString({ length: 128, type: 'alphanumeric' })
})
sessionId: string
或
@PrimaryColumn({
name: 'session_id',
default: () => 'cryptoRandomString({ length: 128, type: "alphanumeric" })' // Why would that even work
})
sessionId: string
或
@PrimaryColumn({
name: 'session_id',
default: 'cryptoRandomString({ length: 128, type: "alphanumeric" })' // Why would that even work
})
sessionId: string
或
@PrimaryColumn({
name: 'session_id',
default: 'please work'
})
sessionId: string
或者不在 @PrimaryColumn()
中设置 default
而是使用 @BeforeInsert()
,使用 .save()
时显然不会调用它
@BeforeInsert()
beforeInsertAction(): void {
this.sessionId = cryptoRandomString({ length: 128, type: 'alphanumeric' })
}
唯一可行的是使用 UserSession
class 的构造函数并在其中设置 sessionId
(我认为这有点违背 default
TypeORM 中的值?):
constructor(
userId: string
) {
this.userId = userId
this.sessionId = cryptoRandomString({ length: 128, type: 'alphanumeric' })
}
并用
调用它
const session = await this.userSessionRepository.save(new UserSession(userId))
所以,我错过了什么吗?首先,我是不是完全错误地处理了这件事?我不知道了。
我最终找到了解决问题的方法...
我现在这样定义我的实体 class:
@Entity('user')
export class User {
@PrimaryColumn({
name: 'user_id',
type: 'varchar',
length: 32
})
userId: string = cryptoRandomString({ length: 32, type: 'alphanumeric' })
@Column({
name: 'session_id',
type: 'varchar',
length: 128
})
sessionId: string = cryptoRandomString({ length: 128, type: 'alphanumeric' })
@Column({
name: 'email',
type: 'varchar',
length: 128
})
email: string
}
现在我可以使用存储库的 .create()
:
创建我的新用户实体
const user: User = this.userRepo.create({ email: 'hello.world@example.com' })
创建以下对象:
user: {
userId: 'ivWW8oMGD8oMh2FL0vM3Grrh2FL0M3Di'
sessionId: 'vM3DiW8oMGrh2FL0vM3DiW8oMGrh2FL0vM3DiW8oMGrh2FL0vM3DiW8oMGrh2FL0...'
email: 'hello.world@example.com'
}
然后可以使用 .save()
方法再次保存:
await this.userRepo.save(user)
尝试使用 TypeORM(在 NestJs 中)将实体保存到具有默认值的主列的数据库时遇到问题。
TL;DR 当 default
似乎什么都没做时,你究竟如何使用 TypeORM 设置默认列值?
编辑 1:好的,所以 default
似乎是数据库级别,之前有点错过了,但仍然 @BeforeInsert()
应该可以解决问题(但还没有)。
编辑 2:显然 @BeforeInsert()
挂钩有效,但前提是 .save()
是用 .save(new UserSession(userId))
而不是 .save({ userId: userId })
调用的(这当然需要适当的构造函数UserSession
).
设置
我有实体 UserSession
,注意 sessionId
字段,它的默认值应该是 cryptoRandomString({ length: 128, type: 'alphanumeric' })
returns.
@Entity('user_session')
export class UserSession {
@PrimaryColumn({
name: 'session_id',
default: () => cryptoRandomString({ length: 128, type: 'alphanumeric' })
})
sessionId: string
@Column({
name: 'user_id',
})
userId: string
}
然后我使用 TypeORM 存储库 .save()
函数将对象写入数据库,如下所示:
@Injectable()
export class AuthService {
constructor(
@InjectRepository(UserSession)
private readonly userSessionRepository: Repository<UserSession>
) {}
async createNewSession(userId: string): Promise<void> {
// Create new session
const session = await this.userSessionRepository.save({
userId: userId
})
// If only it got that far...
}
}
错误
在这一点上,如果没有设置 'manually',我希望 TypeORM 为 sessionId
设置一个默认值。但是,它只是抛出一个错误:
[Nest] 23088 - 04/06/2021, 23:18:44 [ExceptionsHandler] ER_NO_DEFAULT_FOR_FIELD: Field 'session_id' doesn't have a default value +4032ms
QueryFailedError: ER_NO_DEFAULT_FOR_FIELD: Field 'session_id' doesn't have a default value
at new QueryFailedError (E:\SAC\projects\api-flexrent\node_modules\typeorm\error\QueryFailedError.js:12:28)
at Query.<anonymous> (E:\SAC\projects\api-flexrent\node_modules\typeorm\driver\mysql\MysqlQueryRunner.js:217:45)
at Query.<anonymous> (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\Connection.js:526:10)
at Query._callback (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\Connection.js:488:16)
at Query.Sequence.end (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
at Query.ErrorPacket (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\sequences\Query.js:92:8)
at Protocol._parsePacket (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\Protocol.js:291:23)
at Parser._parsePacket (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\Parser.js:433:10)
at Parser.write (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\Parser.js:43:10)
at Protocol.write (E:\SAC\projects\api-flexrent\node_modules\mysql\lib\protocol\Protocol.js:38:16)
绝望
在旧 google 上花了一些时间后,我尝试了几种变体,但都不起作用(并抛出相同的错误):
@PrimaryColumn({
name: 'session_id',
default: cryptoRandomString({ length: 128, type: 'alphanumeric' })
})
sessionId: string
或
@PrimaryColumn({
name: 'session_id',
default: () => 'cryptoRandomString({ length: 128, type: "alphanumeric" })' // Why would that even work
})
sessionId: string
或
@PrimaryColumn({
name: 'session_id',
default: 'cryptoRandomString({ length: 128, type: "alphanumeric" })' // Why would that even work
})
sessionId: string
或
@PrimaryColumn({
name: 'session_id',
default: 'please work'
})
sessionId: string
或者不在 @PrimaryColumn()
中设置 default
而是使用 @BeforeInsert()
,使用 .save()
@BeforeInsert()
beforeInsertAction(): void {
this.sessionId = cryptoRandomString({ length: 128, type: 'alphanumeric' })
}
唯一可行的是使用 UserSession
class 的构造函数并在其中设置 sessionId
(我认为这有点违背 default
TypeORM 中的值?):
constructor(
userId: string
) {
this.userId = userId
this.sessionId = cryptoRandomString({ length: 128, type: 'alphanumeric' })
}
并用
调用它const session = await this.userSessionRepository.save(new UserSession(userId))
所以,我错过了什么吗?首先,我是不是完全错误地处理了这件事?我不知道了。
我最终找到了解决问题的方法...
我现在这样定义我的实体 class:
@Entity('user')
export class User {
@PrimaryColumn({
name: 'user_id',
type: 'varchar',
length: 32
})
userId: string = cryptoRandomString({ length: 32, type: 'alphanumeric' })
@Column({
name: 'session_id',
type: 'varchar',
length: 128
})
sessionId: string = cryptoRandomString({ length: 128, type: 'alphanumeric' })
@Column({
name: 'email',
type: 'varchar',
length: 128
})
email: string
}
现在我可以使用存储库的 .create()
:
const user: User = this.userRepo.create({ email: 'hello.world@example.com' })
创建以下对象:
user: {
userId: 'ivWW8oMGD8oMh2FL0vM3Grrh2FL0M3Di'
sessionId: 'vM3DiW8oMGrh2FL0vM3DiW8oMGrh2FL0vM3DiW8oMGrh2FL0vM3DiW8oMGrh2FL0...'
email: 'hello.world@example.com'
}
然后可以使用 .save()
方法再次保存:
await this.userRepo.save(user)