title: TypeORM: Default values for primary column
body: <p>I have a problem when trying to save an entity to the DB with a primary column with a default value using TypeORM (in NestJs).</p>
  <p><strong>TL;DR</strong> How on earth do you set default column values with TypeORM when <code>default</code> just doesn't seem to do anything?</p>
  <p>EDIT 1: Okay, so <code>default</code> seems to be DB level, kind of missed that before, but still <code>@BeforeInsert()</code> should do the trick then (yet doesn't).</p>
  <p>EDIT 2: So apparently <code>@BeforeInsert()</code> hook works but only if <code>.save()</code> is called with <code>.save(new UserSession(userId))</code> and not with <code>.save({ userId: userId })</code> (which of course requires the appropriate constructor in <code>UserSession</code>).</p>
  <h2>The setup</h2>
  <p>I have the entity <code>UserSession</code>, note the <code>sessionId</code> field, which is supposed to have a default value of whatever <code>cryptoRandomString({ length: 128, type: 'alphanumeric' })</code> returns.</p>
  <pre class="lang-js prettyprint-override"><code>@Entity('user_session')
  export class UserSession {
      
      @PrimaryColumn({ 
          name: 'session_id',
          default: () =&gt; cryptoRandomString({ length: 128, type: 'alphanumeric' })
      })
      sessionId: string
      
      @Column({ 
          name: 'user_id',
      })
      userId: string
     
  }
  </code></pre>
  <p>I then use the TypeORM repository <code>.save()</code> function to write the object to the database like so:</p>
  <pre class="lang-js prettyprint-override"><code>@Injectable()
  export class AuthService {
      constructor(
          @InjectRepository(UserSession)
          private readonly userSessionRepository: Repository&lt;UserSession&gt;
      ) {}
  
      async createNewSession(userId: string): Promise&lt;void&gt; {
          // Create new session
          const session = await this.userSessionRepository.save({
              userId: userId
          })
  
         // If only it got that far...
      }
  }
  </code></pre>
  <h2>The error</h2>
  <p>At this point I kind of expect TypeORM to set a default value for <code>sessionId</code> if nothing is set 'manually'. However, it just throws an error:</p>
  <pre><code>[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.&lt;anonymous&gt; (E:\SAC\projects\api-flexrent\node_modules\typeorm\driver\mysql\MysqlQueryRunner.js:217:45)
      at Query.&lt;anonymous&gt; (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)
  </code></pre>
  <h2>Despair</h2>
  <p>After spending some time on good old google I tried several variations, which all did not work (and throw the same error):</p>
  <pre class="lang-js prettyprint-override"><code>@PrimaryColumn({ 
      name: 'session_id',
      default: cryptoRandomString({ length: 128, type: 'alphanumeric' })
  })
  sessionId: string
  </code></pre>
  <p>or</p>
  <pre class="lang-js prettyprint-override"><code>@PrimaryColumn({ 
      name: 'session_id',
      default: () =&gt; 'cryptoRandomString({ length: 128, type: &quot;alphanumeric&quot; })' // Why would that even work
  })
  sessionId: string
  </code></pre>
  <p>or</p>
  <pre class="lang-js prettyprint-override"><code>@PrimaryColumn({ 
      name: 'session_id',
      default: 'cryptoRandomString({ length: 128, type: &quot;alphanumeric&quot; })' // Why would that even work
  })
  sessionId: string
  </code></pre>
  <p>or</p>
  <pre class="lang-js prettyprint-override"><code>@PrimaryColumn({ 
      name: 'session_id',
      default: 'please work'
  })
  sessionId: string
  </code></pre>
  <p>or not setting <code>default</code> in <code>@PrimaryColumn()</code> but rather using <code>@BeforeInsert()</code>, which apparently isn't called when using <code>.save()</code></p>
  <pre class="lang-js prettyprint-override"><code>@BeforeInsert()
  beforeInsertAction(): void {
      this.sessionId = cryptoRandomString({ length: 128, type: 'alphanumeric' })
  }
  </code></pre>
  <p>The only thing that did work was using a constructor for the <code>UserSession</code> class and setting the <code>sessionId</code> in there (which I thought kind of defeats the purpose of <code>default</code> values in TypeORM?):</p>
  <pre class="lang-js prettyprint-override"><code>constructor(
      userId: string
  ) {
      this.userId = userId
      this.sessionId = cryptoRandomString({ length: 128, type: 'alphanumeric' })
  }
  </code></pre>
  <p>and calling it with</p>
  <pre class="lang-js prettyprint-override"><code>const session = await this.userSessionRepository.save(new UserSession(userId))
  </code></pre>
  <p>So, did I miss anything? Am I approaching the thing completely wrong, to begin with? I don't know anymore.</p>