Encountering an issue while attempting to save an entity to the database in NestJs using TypeORM due to a primary column with a default value not being set.
Summary How can I successfully define default column values in TypeORM when the default
property appears ineffective?
UPDATE 1: Realized that default
operates at the database level, although utilizing @BeforeInsert()
does not resolve the issue as expected.
UPDATE 2: Discovered that the @BeforeInsert()
hook functions only if .save()
is invoked using .save(new UserSession(userId))
rather than .save({ userId: userId })
, necessitating the appropriate constructor in UserSession
.
The Scenario
In my entity UserSession
, take note of the sessionId
field intended to possess a default value generated by
cryptoRandomString({ length: 128, type: 'alphanumeric' })
.
@Entity('user_session')
export class UserSession {
@PrimaryColumn({
name: 'session_id',
default: () => cryptoRandomString({ length: 128, type: 'alphanumeric' })
})
sessionId: string
@Column({
name: 'user_id',
})
userId: string
}
I utilize the TypeORM repository's .save()
method to store the object in the database as shown below:
@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
})
// Unfortunately, encountering issues...
}
}
The Issue
Anticipating TypeORM to assign a default value to sessionId
if left unset manually, yet an error is thrown instead:
[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)
...
Confusion
After exploring various options without success and encountering the same error repeatedly:
@PrimaryColumn({
name: 'session_id',
default: cryptoRandomString({ length: 128, type: 'alphanumeric' })
})
sessionId: string
or
@PrimaryColumn({
name: 'session_id',
default: () => 'cryptoRandomString({ length: 128, type: "alphanumeric" })'
})
sessionId: string
or
@PrimaryColumn({
name: 'session_id',
default: 'cryptoRandomString({ length: 128, type: "alphanumeric" })'
})
sessionId: string
or
@PrimaryColumn({
name: 'session_id',
default: 'please work'
})
sessionId: string
or alternatively avoiding specifying default
within @PrimaryColumn()
and opting for @BeforeInsert()
, which seems inactive when using .save()
:
@BeforeInsert()
beforeInsertAction(): void {
this.sessionId = cryptoRandomString({ length: 128, type: 'alphanumeric' })
}
The lone successful approach involved employing a constructor in the UserSession
class to set the sessionId
:
constructor(
userId: string
) {
this.userId = userId
this.sessionId = cryptoRandomString({ length: 128, type: 'alphanumeric' })
}
and invoking it via
const session = await this.userSessionRepository.save(new UserSession(userId))
Have I overlooked something critical? Is my methodology fundamentally flawed from the outset? Uncertainty prevails.