Back to Entity Mapping: Keys, Columns & Annotations
Q8Question 8 of 8

@Column mapping and @Transient?

Key Concepts
  • @Column tunes field-to-column mapping: name, nullable, length, precision/scale, unique, insertable, updatable, and columnDefinition.
  • For money always use precision and scale on a BigDecimal (e.g., precision=15, scale=2), never length.
  • updatable=false prevents the column from appearing in UPDATE statements, perfect for createdAt timestamps.
  • JPA @Transient excludes a field from DATABASE mapping; the field is not persisted to any column.
  • Java transient keyword excludes a field from JAVA serialization only; it does NOT affect JPA mapping.
  • Confusing the two is a common bug: the keyword does not exclude from the database, only the annotation does.

Definition

@Column tunes name, nullability, length, precision/scale, uniqueness, and insert/update inclusion; JPA @Transient excludes from the database, Java transient excludes from serialization.
  • @Column – fine-tunes how an entity field maps to a database column: name, nullable, length, precision, scale, unique, updatable, insertable, and columnDefinition.
  • precision/scale – for BigDecimal money fields, precision is the total number of digits, scale is the number after the decimal point (e.g., DECIMAL(15,2)).
  • updatable=false – excludes the column from generated UPDATE statements, so the value is set once on INSERT and never changed.
  • JPA @Transient – tells the persistence provider not to map the field to any column; the field is excluded from all SQL.
  • Java transient keyword – tells Java's built-in Serializable mechanism to skip the field during object serialization; it has nothing to do with JPA.
  • Common confusion – the Java transient keyword does NOT exclude a field from the database; only the JPA @Transient annotation does.

@Column is the instruction sheet telling the bank's filing clerk at National Bank of India exactly which box each piece of customer data goes into, how long the box can be, and whether the box is allowed to be empty. JPA @Transient is a sticky note saying this scratch calculation does NOT get filed in the vault at all, like a derived total you compute on screen but never store. Java's transient keyword is a totally different note that only matters when you photocopy the whole file to send elsewhere (serialization), telling the photocopier to leave that field blank.

Understanding the Concepts

What does @Column control?

@Column fine-tunes how an entity field maps to a database column. Without it, Hibernate applies its naming strategy and default types. With it, you control the exact column name, nullability, size, precision, uniqueness, and whether the column participates in INSERT and UPDATE statements.

JAVA
package com.bank.model;

import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;

@Entity
@Table(name = "accounts")
public class Account {

    @Id
    @Column(name = "account_id")
    private String accountId;

    @Column(name = "holder_name", nullable = false, length = 100)
    private String holderName;

    @Column(name = "balance", nullable = false, precision = 15, scale = 2)
    private BigDecimal balance;    // DECIMAL(15,2) -- correct for money

    @Column(name = "pan", nullable = false, unique = true, length = 10)
    private String pan;

    @Column(name = "created_at", updatable = false)
    private LocalDateTime createdAt;   // set once on INSERT, never on UPDATE

    @Column(name = "notes", columnDefinition = "TEXT")
    private String notes;              // forces TEXT type instead of VARCHAR
}
TEXT
Generated DDL:
  holder_name VARCHAR(100) NOT NULL,
  balance DECIMAL(15,2) NOT NULL,
  pan VARCHAR(10) NOT NULL UNIQUE,
  created_at TIMESTAMP,
  notes TEXT

Why use precision and scale for money?

For money fields, always use precision and scale on a BigDecimal. Never use length, which is for VARCHAR sizing. precision is the total number of digits, scale is the number after the decimal point. DECIMAL(15,2) means up to 15 total digits with 2 after the decimal, which stores amounts up to 9,999,999,999,999.99.

JAVA
// WRONG: using length for money
@Column(name = "balance", length = 15)          // length is for VARCHAR, not DECIMAL!
private BigDecimal balance;

// CORRECT: using precision and scale for money
@Column(name = "balance", precision = 15, scale = 2)  // DECIMAL(15,2)
private BigDecimal balance;
TEXT
DECIMAL(15,2) stores:
- Maximum: 9,999,999,999,999.99  (15 digits total, 2 after decimal)
- Minimum: -9,999,999,999,999.99
- Exact arithmetic, no floating-point rounding errors
- Essential for banking: Rs. 1,50,000.50 stored as 150000.50 exactly

What do insertable and updatable control?

updatable=false means the column is set on INSERT but Hibernate never includes it in an UPDATE. This is exactly right for a createdAt timestamp that must never change. insertable=false and updatable=false together make a field read-only from the ORM's point of view.

JAVA
package com.bank.model;

import jakarta.persistence.*;
import java.time.LocalDateTime;

@Entity
public class Account {

    @Id
    private String accountId;

    @Column(name = "created_at", updatable = false)
    private LocalDateTime createdAt;   // set once on INSERT, never UPDATEd

    @Column(name = "updated_at")
    private LocalDateTime updatedAt;   // updated on every save

    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
        // createdAt is NOT in the UPDATE SQL because updatable=false
    }
}
TEXT
INSERT: INSERT INTO accounts (account_id, created_at, updated_at) VALUES (..., '2026-01-15', '2026-01-15')
UPDATE: UPDATE accounts SET updated_at = '2026-06-15' WHERE account_id = 'SAV2001'
        (created_at is NOT in the UPDATE because updatable=false)

What is JPA @Transient?

JPA's @Transient annotation means this field is NOT a persistent property: never put it in any SQL. The field exists in Java for runtime use but is excluded from all INSERT, UPDATE, and SELECT statements. It is not stored in the database.

JAVA
package com.bank.model;

import jakarta.persistence.*;
import java.math.BigDecimal;

@Entity
public class Account {

    @Id
    private String accountId;

    @Column(precision = 15, scale = 2)
    private BigDecimal balance;

    @Column(precision = 15, scale = 2)
    private BigDecimal holdAmount;

    @Transient
    private BigDecimal availableForWithdrawal;  // computed, never stored

    @PostLoad
    protected void computeAvailable() {
        availableForWithdrawal = balance.subtract(holdAmount);
    }
}
TEXT
@Transient behaviour:
- availableForWithdrawal is NOT in any SQL (no column in the table)
- Computed from balance and holdAmount after loading (@PostLoad)
- Useful for derived values, display totals, runtime state

What is the Java transient keyword?

Java's transient keyword is from core Java and has nothing to do with databases. It tells Java's built-in Serializable serialization to skip the field when the object is turned into a byte stream. It does NOT affect JSON serialization by Jackson, and it does NOT affect JPA mapping.

JAVA
package com.bank.model;

import jakarta.persistence.*;

@Entity
public class Account {

    @Id
    private String accountId;

    private transient String sessionCache;   // skipped by Java Serializable
    // BUT: sessionCache IS still a database column unless also @Transient!
}
TEXT
Java transient keyword:
- Affects: ObjectOutputStream / ObjectInputStream (Java serialization)
- Does NOT affect: JPA persistence (still a DB column!)
- Does NOT affect: Jackson JSON serialization
- Common trap: developer uses 'transient' expecting it to exclude from DB

How do JPA @Transient and Java transient differ?

| Aspect | JPA @Transient | Java transient keyword |
|---|---|---|
| Mechanism | JPA annotation | Java language keyword |
| Excludes from | Database mapping (SQL) | Java Serializable byte stream |
| Affects JPA | Yes: field not persisted | No: field IS persisted |
| Affects Jackson JSON | No | No |
| Affects ObjectOutputStream | No | Yes |
| Use case | Computed fields, runtime state | Sensitive data in serialization |

JAVA
package com.bank.model;

import jakarta.persistence.*;

@Entity
public class Account {

    @Id
    private String accountId;

    @Transient                            // excluded from DB
    private java.math.BigDecimal displayTotal;

    private transient String tempCache;   // excluded from Java serialization
    // BUT tempCache IS still a DB column!

    @Transient                            // excluded from DB
    private transient String scratch;     // excluded from BOTH DB and serialization
}

What are common mistakes?

The most dangerous mistake is assuming the Java transient keyword excludes a field from the database. It does not. If you want a field excluded from persistence, you MUST use the JPA @Transient annotation.

JAVA
// WRONG: using Java transient to exclude from database
package com.bank.model;

import jakarta.persistence.*;

@Entity
public class BrokenAccount {

    @Id
    private String accountId;

    private transient String internalNote;  // STILL a DB column!
    // Developer expected it to be excluded from the database
    // But 'transient' only affects Java serialization, not JPA
}
JAVA
// CORRECT: using JPA @Transient to exclude from database
package com.bank.model;

import jakarta.persistence.*;

@Entity
public class CorrectAccount {

    @Id
    private String accountId;

    @Transient
    private String internalNote;  // NOT a DB column (correct)
}

What about @Column with columnDefinition?

columnDefinition lets you specify exact DDL when the default type is not what you want. Use it for database-specific types like TEXT, JSONB, or explicit constraints.

JAVA
package com.bank.model;

import jakarta.persistence.*;

@Entity
public class Account {

    @Id
    private String accountId;

    @Column(name = "notes", columnDefinition = "TEXT")
    private String notes;   // TEXT instead of VARCHAR(255)

    @Column(name = "metadata", columnDefinition = "JSONB")
    private String metadata;  // PostgreSQL JSONB type
}

What should a senior engineer know?

A senior engineer always uses precision and scale for money, never length. They use updatable=false for createdAt timestamps. They use the JPA @Transient annotation for computed fields and never rely on the Java transient keyword for database exclusion. They keep annotations consistently on fields to avoid mixed field-and-property access surprises.

JAVA
package com.bank.model;

import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;

@Entity
@Table(name = "accounts")
public class Account {

    @Id
    @Column(name = "account_id")
    private String accountId;

    @Column(name = "holder_name", nullable = false, length = 100)
    private String holderName;

    @Column(name = "balance", nullable = false, precision = 15, scale = 2)
    private BigDecimal balance;

    @Column(name = "pan", nullable = false, unique = true, length = 10)
    private String pan;

    @Column(name = "created_at", updatable = false)
    private LocalDateTime createdAt;

    @Transient
    private BigDecimal availableBalance;  // computed at @PostLoad, not stored

    @PostLoad
    protected void computeAvailable() {
        availableBalance = balance;  // simplified for example
    }
}

Visual Overview

TEXT
  @Column Attributes
  ============================================

  @Column(
    name = "holder_name",    -> column name in DDL
    nullable = false,        -> NOT NULL constraint
    length = 100,            -> VARCHAR(100)
    precision = 15,          -> DECIMAL total digits
    scale = 2,               -> DECIMAL decimal places
    unique = true,           -> UNIQUE constraint
    updatable = false,       -> excluded from UPDATE SQL
    insertable = false,      -> excluded from INSERT SQL
    columnDefinition = "TEXT" -> raw DDL type override
  )

  JPA @Transient vs Java transient
  ============================================

  Field: displayTotal
  +---------------------+
  | @Transient          |  -> NOT in database (no column)
  | (JPA annotation)    |  -> NOT in INSERT/UPDATE/SELECT
  +---------------------+  -> still in Jackson JSON

  Field: sessionCache
  +---------------------+
  | transient           |  -> NOT in ObjectOutputStream
  | (Java keyword)      |  -> STILL in database (has column!)
  +---------------------+  -> still in Jackson JSON

  Field: scratch
  +---------------------+
  | @Transient          |  -> NOT in database
  | + transient         |  -> NOT in ObjectOutputStream
  | (both)              |  -> excluded from BOTH
  +---------------------+

Key Takeaway

The @Column annotation lets Rajesh control exactly how an entity field maps to a database column at National Bank of India. He sets the column name to bridge camelCase fields to snake_case columns, nullable=false to add a NOT NULL constraint, precision and scale for exact money storage, and updatable=false for timestamps that must never change after creation. For money he always uses precision=15, scale=2 on a BigDecimal, never length, so a balance maps to DECIMAL(15,2) which stores rupees and paise exactly without floating-point rounding.

The transient distinction is a classic interview trap and a real bug source. JPA @Transient means the field is not persistent at all, excluded from every SQL statement. The Java transient keyword is completely unrelated to JPA: it only tells Java's built-in serialization to skip the field, and it has no effect on database mapping or Jackson JSON. If Rajesh wants a field kept out of the database, he must use the JPA @Transient annotation. A field can carry both when he wants it out of both the database and Java serialization.

The senior cautions Pankaj gives are to always use the annotation rather than the keyword for excluding fields from persistence, to use precision and scale rather than length for money, and to keep annotations consistently on fields to avoid mixed field-and-property access surprises.

Remember one sentence: @Column tunes name, nullability, precision, and updatability for column mapping, while JPA @Transient excludes from the database and Java transient excludes from serialization.

---

Share
Use ← → arrow keys to navigate