Skip to main content

JPA & Hibernate

Object-Relational Mapping (ORM) and Entities

Modern Java applications utilize Object-Relational Mapping (ORM) technologies to translate language objects and classes into database tables and rows.


1. Difference between JPA and Hibernate

There is a fundamental distinction between the specification standard and its concrete implementation engine:

Clic para ampliar
Detailed Persistence Diagram Explanation
  1. JPA (Jakarta Persistence API): A Java specification defining annotations (@Entity, @Id, @Column) and contracts without containing executable logic.
  2. Hibernate ORM: The default concrete engine chosen by Spring Boot. Reads JPA annotations, translates object operations into SQL dialect statements, and manages persistence sessions.
  3. Relational Database: Physical storage engine where tabular data resides.

2. JPA Entity Mapping and Annotations

An Entity is a POJO (Plain Old Java Object) representing a physical table. Each class instance corresponds to a row in the table.

2.1. Core Mapping Annotations

AnnotationPurposeCommon Attributes
@EntityDeclares the Java class as a JPA-managed entity.name (logical entity name in JPQL)
@TableSpecifies physical database table name.name, schema, uniqueConstraints
@IdMarks field as Primary Key.N/A
@GeneratedValueSpecifies automatic primary key generation strategy.strategy (IDENTITY, SEQUENCE, AUTO, TABLE)
@ColumnConfigures column mapping details.name, nullable, unique, length, precision
@JoinColumnDefines Foreign Key column name in relationships.name, referencedColumnName, nullable
@TransientSpecifies field should NOT be persisted in storage.N/A

3. Relational Database Model (ER Diagram)

Before writing Java code, we design the relational database schema for a product catalog domain:

Clic para ampliar
Detailed ER Diagram Explanation
  • CATEGORIES: Parent table storing product classifications (1 to N with PRODUCTS).
  • SUPPLIERS: Parent table storing supplier companies (1 to N with PRODUCTS).
  • PRODUCTS: Main table containing two Foreign Keys (FK): category_id and supplier_id, physically referencing primary keys (PK) of parent tables.

4. Complete Java Entity Mapping with JPA and Lombok

Below, the ER diagram is mapped into Java entity classes using JPA and Lombok annotations:

4.1. Entity Category (Table categorias)

src/main/java/com/icesi/app/model/Category.java
package com.icesi.app.model;

import jakarta.persistence.*;
import lombok.*;

@Entity
@Table(name = "categorias")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Category {

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

@Column(name = "nombre", nullable = false, length = 80)
private String name;

@Column(name = "descripcion", length = 255)
private String description;
}

4.2. Entity Supplier (Table proveedores)

src/main/java/com/icesi/app/model/Supplier.java
package com.icesi.app.model;

import jakarta.persistence.*;
import lombok.*;

@Entity
@Table(name = "proveedores")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Supplier {

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

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

@Column(name = "nit_ruc", unique = true, nullable = false, length = 50)
private String taxId;
}

4.3. Entity Product with @ManyToOne Relationships (Table productos)

src/main/java/com/icesi/app/model/Product.java
package com.icesi.app.model;

import jakarta.persistence.*;
import lombok.*;

@Entity
@Table(name = "productos")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Product {

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

@Column(name = "nombre_producto", nullable = false, length = 120)
private String name;

@Column(name = "precio", nullable = false, precision = 10, scale = 2)
private Double price;

@Column(name = "codigo_sku", unique = true, nullable = false, length = 50)
private String sku;

// Transient field ignored by JPA
@Transient
private String temporaryDiscountCode;

// Many-to-One: Many products belong to one Category
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "categoria_id", nullable = false)
private Category category;

// Many-to-One: Many products are supplied by one Supplier
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "proveedor_id", nullable = false)
private Supplier supplier;
}

Self-Assessment Quiz

Cargando cuestionario...