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...