Column Mapping

Author Avatar
Learn Here Fun Pedia
5 min read •
Featured Image

Column Mapping — Extremely Important

Column mapping is about telling JPA/Hibernate: How should a Java field/property be represented in the database?

For example, take a look at this basic entity:

@Entity
public class Employee {

    @Id
    private Long id;

    private String name;

    private double salary;
}

Conceptually, this maps directly from Java to the Database:

Java                         Database

Employee                     employee
    |                            |
    |-- id       ───────────→    id
    |-- name     ───────────→    name
    |-- salary   ───────────→    salary

JPA provides several annotations to control this mapping. Let's break them down.

1.1 @Column

@Column is used to customize how a Java field/property maps to a database column. Without it, the provider's default naming rules determine the column name.

Example:

@Column(name = "employee_name")
private String name;

Now, the Java field name maps to the Database column employee_name.

Common @Column attributes:

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

The most important attributes are name, nullable, unique, length, precision, and scale. We'll understand each.

1.2 name

The name attribute is useful when your Java naming and database naming are different.

@Column(name = "employee_name")
private String employeeName;

1.3 nullable

@Column(nullable = false)
private String name;

Conceptually this means the database column should not accept NULL. When schema generation is used, this results in a constraint conceptually like: name VARCHAR(255) NOT NULL.

Important distinction

nullable = false is primarily database schema metadata. It is not the same as application-level validation. For example, @NotNull is Bean Validation, whereas nullable = false describes the database column constraint. For robust applications, you may use both when appropriate.

1.4 unique

@Column(unique = true)
private String email;

This indicates that the column should contain unique values. If schema generation is used, this creates a unique constraint/index depending on the database.

Important production point

For an important business uniqueness rule (such as email uniqueness), you generally want a real database unique constraint, not just application code checks. Concurrent requests can easily bypass a simple "if exists" check. The database should enforce the final constraint.

1.5 length

length is mainly relevant to string columns. It defines the maximum database string length when schema generation applies this metadata.

@Column(length = 100)
private String name;

Conceptually, this maps to name VARCHAR(100). Remember, it is primarily about database definition, not a complete replacement for input validation (like @Size(max = 100)).

1.6 precision & 1.7 scale

These are mainly relevant to numeric values such as BigDecimal.

@Column(precision = 10, scale = 2)
private BigDecimal salary;
  • Precision: Total number of digits.
  • Scale: Number of digits after the decimal point.

For a value like 12345678.90, you have 8 digits before the decimal and 2 digits after the decimal, equaling 10 total digits. Therefore, precision = 10 and scale = 2.

1.8 Precision vs Scale

This is a common interview question. Remember:

  • PRECISION = total digits
  • SCALE = digits after decimal

1.9 Complete @Column Example

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

Conceptually, this generates salary DECIMAL(12,2) NOT NULL (the exact SQL type depends on the dialect).

1.10 @Basic

@Basic represents a basic persistent attribute. However, the most important point is: You usually don't need to write @Basic.

private String name;

This is already treated as a basic persistent attribute under normal JPA rules. It does have optional and fetch attributes, but lazy loading for basic attributes is provider-dependent.

1.11 @Transient

This one is extremely important. @Transient means: Do not persist this field as part of the entity's database state.

@Transient
private double bonus;

If you have a calculated field like a bonus, you can calculate it in Java (bonus = salary * 0.10), but the database table will not have a bonus column.

1.12 @Transient vs Java transient

This is a very common interview trap.

  • JPA @Transient: Don't persist this field to the database.
  • Java transient keyword: Exclude this field from Java serialization.

They solve entirely different problems.

1.13 @Lob

@Lob means: Map the attribute as a large object (LOB) in the database.

  • Character data: @Lob private String description; (Maps to CLOB, TEXT, etc.)
  • Binary data: @Lob private byte[] document; (Maps to BLOB)

Note: In many modern applications, large files are better stored in object storage (S3, Azure) with URLs stored in the relational DB.

1.14 & 1.15 & 1.16 @Enumerated

When mapping an Enum to the database, you use @Enumerated. There are two main strategies:

EnumType.ORDINAL

@Enumerated(EnumType.ORDINAL)
private EmployeeStatus status;

The enum's numeric position (0, 1, 2) is stored. Problem: If you add a new enum value in the middle, the numbers shift, and existing database values will be interpreted incorrectly. Ordinal storage is risky for business enums.

EnumType.STRING

@Enumerated(EnumType.STRING)
private EmployeeStatus status;

The text name (e.g., "ACTIVE") is stored. This is much safer and more readable. Interview recommendation: For business enums, STRING is usually preferred; use ORDINAL carefully.

1.17, 1.18 & 1.19 @Temporal & Modern Dates

Historically, @Temporal(TemporalType.DATE) was used with legacy Java date types like java.util.Date and java.util.Calendar.

With modern Java (8+), we use LocalDate, LocalTime, LocalDateTime, Instant, etc. Modern JPA providers support these directly, so you generally do not use @Temporal with them.

private LocalDate joiningDate;
private LocalDateTime createdAt;

The modern java.time API is preferred because it's easier to reason about, provides clearer types, and handles timezones gracefully in distributed systems.

1.20 Complete Example

Let's put the important column mappings together:

@Entity
@Table(name = "employees")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

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

    @Column(nullable = false, precision = 12, scale = 2)
    private BigDecimal salary;

    @Column(unique = true)
    private String email;

    @Enumerated(EnumType.STRING)
    private EmployeeStatus status;

    private LocalDate joiningDate;

    private LocalDateTime createdAt;

    @Lob
    private String description;

    @Transient
    private double calculatedBonus;
}

1.21 Quick Comparison

Annotation / Attribute Purpose
@ColumnCustomize column mapping
nameSpecify column name
nullableWhether DB column may contain NULL
uniqueUnique constraint metadata
lengthString column length
precisionTotal digits for numeric values
scaleDigits after decimal
@BasicMarks/configures a basic persistent attribute; usually implicit
@TransientExcludes field from persistence
@LobMaps large text/binary data
@EnumeratedMaps Java enum to DB
EnumType.STRINGStores enum name
EnumType.ORDINALStores enum position
@TemporalLegacy Date/Calendar temporal mapping
java.timeModern date/time mapping; normally no @Temporal

Final Mental Model Summary

  • @Column: Control DB column metadata (name, length, constraints).
  • @Transient: Do not persist this field in the database.
  • @Lob: Used for Large Objects (CLOB/BLOB text or binary).
  • @Enumerated: Used for Enum mapping (Prefer STRING over ORDINAL).
  • @Temporal: Legacy. Use modern LocalDate / LocalDateTime without it.
  • Precision & Scale: Precision is total digits, Scale is decimal digits.

The next important piece after this is @Access (FIELD vs PROPERTY) and how Hibernate decides whether it reads fields or getters/setters!

5.22 T3 Interview Questions (FAQs)

Q1. What is the difference between @Column and @Basic?

@Column controls database column mapping and schema-related attributes such as name, nullability, uniqueness, length, precision, and scale. @Basic describes a basic persistent attribute and is usually implicit, so it is rarely necessary to write explicitly.

Q2. Difference between @Transient and transient?

JPA's @Transient stops a field from being persisted to the database. Java's transient keyword stops a field from being included in standard Java serialization. They are unrelated mechanisms.

Q3. Why prefer EnumType.STRING over ORDINAL?

Because ordinal values depend on enum positions. If enum constants are reordered or inserted, existing numeric database values can represent the wrong enum constant. STRING stores names such as "ACTIVE", which is generally safer for persistent business data.

Q4. What is precision vs scale?

Precision is the total number of digits. Scale is the number of digits after the decimal point. For 123456.78, precision = 8 and scale = 2.

Q5. Is @Temporal required for LocalDate?

No. @Temporal is for legacy temporal types such as java.util.Date and Calendar. Modern Java time types (LocalDate, LocalDateTime, Instant) are mapped directly by modern JPA providers.

Q6. Does @Column(nullable = false) validate a REST request?

No, not by itself. It primarily describes the database column constraint. For request validation, use Bean Validation where appropriate (like @NotNull) and use the database constraint as the final integrity boundary.

➔ Read more about Fundamentals ➔ Read more about Variables and Storage Classes ➔ Read more about Operators ➔ Read more about Control Statements and Loops ➔ Read more about Functions ➔ Read more about Arrays ➔ Read more about Pointers ➔ Read more about String ➔ Read more about Structures ➔ Read more about Enum ➔ Read more about Union

Comments (0)