Popular Searches
Popular Course Categories
Popular Courses

Introduction to Object-Relational Mapping (ORM)

Introduction to Object-Relational Mapping (ORM)

Hibernate ORM and Persistence Fundamentals

Introduction to Object-Relational Mapping (ORM)

Course: Advanced Java Training

Topic: Introduction to Object-Relational Mapping (ORM)

Course Link: Advanced Java Training Course

Demo Link: Register for a Free Course Demo

Website: JustAcademy Official Website


1. Introduction to ORM

Object-Relational Mapping (ORM) is a programming technique that connects object-oriented application code with a relational database. In Java applications, ORM allows developers to work with Java objects instead of manually converting every database row into an object and every object into SQL statements.

Java applications commonly use classes and objects to represent real-world entities, such as students, employees, products, and orders. Relational databases, on the other hand, store information in tables containing rows and columns. ORM helps map these two representations to each other.

For example, a Java application may contain an Employee object with properties such as employeeId, name, email, and salary. ORM can map this object to a corresponding row in an employees database table.

2. What Is Object-Relational Mapping?

Object-Relational Mapping is a technique for mapping object-oriented program structures to relational database structures. It enables developers to create, read, update, and delete persistent data through objects and ORM APIs.

ORM tools can manage many common database operations, generate SQL queries, map query results to objects, and coordinate changes with database transactions.

Simple definition: ORM acts as a bridge between Java objects and relational database tables.

Example of ORM Mapping

Java Object Concept Relational Database Concept
Java class Database table
Object instance Table row or entity record
Object field or property Table column
Object identifier Primary key
Object relationship Foreign key or join table relationship
Object persistence Saving data in the database

3. Why Is ORM Needed in Java?

Java applications often need to store and retrieve data from databases such as MySQL, PostgreSQL, Oracle, and SQL Server. JDBC provides a standard way to communicate with relational databases, but developers using JDBC directly commonly write repetitive code for SQL execution, parameter binding, result processing, and resource management.

ORM reduces much of this repetitive persistence code by mapping database records to Java objects and providing APIs for common data operations.

Common Problems Without ORM

  • Writing repetitive SQL statements for common database operations.
  • Manually converting query results into Java objects.
  • Maintaining mappings between Java fields and database columns.
  • Managing relationships between related records.
  • Handling database transactions and persistence state.
  • Updating data-access code when database mappings change.

How ORM Helps

  • Maps Java classes to database tables.
  • Maps Java fields to database columns.
  • Provides APIs for saving, finding, updating, and deleting entities.
  • Supports entity relationships, such as one-to-one and one-to-many.
  • Works with transaction management and database querying facilities.
  • Can provide caching and query optimizations when configured appropriately.

4. Understanding Object-Relational Impedance Mismatch

Object-relational impedance mismatch refers to the differences between object-oriented programming models and relational database models. Java represents data through objects and references, while relational databases represent data using tables, rows, columns, primary keys, and foreign keys.

ORM tools help manage these differences, but they do not eliminate every design or performance challenge.

Difference Java Object Model Relational Model
Structure Classes and objects Tables and rows
Relationships Object references and collections Foreign keys and join tables
Inheritance Supported through class inheritance Requires a database mapping strategy
Identity Object references and equality rules Primary keys identify records
Data access Access fields and navigate references Execute queries to retrieve rows

5. What Is Persistence?

Persistence means keeping data available after an application finishes running. Data stored only in an ordinary Java object generally exists in memory and can be lost when the application terminates. Persistent data is stored in a durable system, such as a relational database, and can be retrieved later.

ORM frameworks help persist Java objects by translating their state into database operations.

Example

Imagine a student registration application. When a student submits a registration form, the application creates a Student object. ORM can store that student's details in a database. When the application restarts, it can retrieve the record and reconstruct a Student entity.

6. How ORM Works

ORM generally works by using mapping metadata to understand how Java entities correspond to database structures. The application interacts with the ORM API, and the ORM generates or executes suitable SQL operations through a database connection.

  1. Define an entity: Create a Java class that represents persistent data.
  2. Configure mapping: Identify the database table, columns, primary key, and relationships.
  3. Initialize the ORM: Configure the persistence provider and database connection.
  4. Perform an operation: Save, retrieve, update, or delete an entity using the ORM API.
  5. Generate database operations: The ORM prepares and executes SQL as needed.
  6. Synchronize changes: Changes are synchronized with the database, usually within a transaction.
  7. Return results: Retrieved database records are represented as Java entities or query results.

Basic ORM Flow

Java Application
       |
       v
Java Entity Objects
       |
       v
ORM Framework
       |
       v
SQL Generation and Execution
       |
       v
Relational Database
       |
       v
Query Results Mapped to Java Objects

7. Popular ORM Technologies in Java

Several technologies are available for implementing ORM in Java. They have different APIs and capabilities.

Technology Description
Hibernate ORM A widely used Java ORM framework that also implements the Jakarta Persistence specification.
Jakarta Persistence (JPA) A standard specification defining APIs and mapping rules for persistence in Java. It is not itself a specific ORM implementation.
EclipseLink A persistence framework that implements Jakarta Persistence and supports ORM features.
Apache OpenJPA A Java persistence implementation supporting Jakarta Persistence APIs.
MyBatis A SQL mapping framework that maps SQL statements and results to Java objects; it is often described as a SQL mapper rather than a full ORM.

8. Understanding Hibernate and JPA

Hibernate ORM is a framework that helps Java applications work with relational data through object-oriented APIs. It can be used through its native API or as an implementation of Jakarta Persistence.

Jakarta Persistence, historically known as Java Persistence API (JPA), defines standard interfaces and annotations for entity mapping, persistence operations, queries, and relationships. A provider such as Hibernate implements those standard APIs.

Hibernate and JPA: Key Differences

JPA / Jakarta Persistence Hibernate ORM
A persistence specification and API. A concrete ORM framework and persistence provider.
Defines standard annotations and interfaces. Implements those APIs and provides additional Hibernate-specific features.
Supports provider portability when standard APIs are used. Can be accessed through standard JPA APIs or its native APIs.
Does not independently execute database operations without an implementation. Performs ORM work when configured with the required dependencies and database connection.

9. Basic ORM Mapping with a Java Entity

In Jakarta Persistence, an entity is a Java class whose instances can be stored in a relational database. The @Entity annotation marks the class as an entity, while @Id identifies its primary key.

The following example uses the modern jakarta.persistence package namespace. Older projects may use javax.persistence, depending on the version of the persistence framework.

Example: Employee Entity

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Column;

@Entity
public class Employee {

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

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

    @Column(unique = true, length = 150)
    private String email;

    private double salary;

    public Employee() {
    }

    public Employee(String name, String email, double salary) {
        this.name = name;
        this.email = email;
        this.salary = salary;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

Explanation of the Code

  • @Entity marks the Employee class as a persistent entity.
  • @Id identifies the primary key field.
  • @GeneratedValue configures primary-key generation according to the selected strategy and database support.
  • @Column customizes column mapping and constraints.
  • The no-argument constructor supports entity instantiation by the persistence provider.
  • Getters and setters provide access to the object's properties.

Unless a table name is specified with @Table, the persistence provider determines the table mapping according to its naming rules and configuration. Database schema creation or migration must also be configured separately.

10. Mapping Java Classes to Database Tables

A Java entity can map to a database table. By default, the persistence provider uses its naming rules, but annotations can make the mapping explicit.

Example with an Explicit Table Name

import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import jakarta.persistence.Id;
import jakarta.persistence.Column;

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

    @Id
    private Long id;

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

    @Column(name = "employee_email")
    private String email;

    public Employee() {
    }
}

In this example, the Employee entity maps to the employees table. The Java field name maps to the database column employee_name.

11. Mapping Java Data Types to Database Columns

ORM frameworks map Java data types to compatible database column types. The final SQL type depends on the persistence provider, database dialect, annotations, and schema configuration.

Java Type Typical Database Representation Common Use
String VARCHAR, CHAR, or a text type Names, emails, descriptions
int / Integer INTEGER Counts and numeric identifiers
long / Long BIGINT Large integer values or identifiers
double DOUBLE or an equivalent floating-point type Approximate decimal calculations
BigDecimal DECIMAL or NUMERIC Financial amounts requiring decimal precision
LocalDate DATE Calendar dates
LocalDateTime TIMESTAMP or equivalent Date and time without a time-zone offset
boolean / Boolean BOOLEAN or a database-specific equivalent True/false values

12. Primary Keys and Entity Identity

A primary key uniquely identifies a row in a database table. ORM uses an entity's identifier to distinguish persistent records and manage entity state.

Common identifier strategies include:

  • IDENTITY: The database generates the identifier, often using an identity column.
  • SEQUENCE: A database sequence supplies identifier values where supported.
  • AUTO: The provider chooses an appropriate strategy based on the environment.
  • Assigned identifier: The application supplies the identifier value itself.

Choose an identifier strategy that matches the database and application requirements. Do not assume that every strategy behaves identically across all databases.

13. CRUD Operations in ORM

CRUD stands for Create, Read, Update, and Delete. These operations form the foundation of most data-driven applications. ORM frameworks provide APIs that help perform CRUD operations on entities.

Operation Purpose Example
Create Store a new record. Register a new employee.
Read Retrieve existing records. Find an employee by identifier.
Update Modify stored information. Change an employee's email.
Delete Remove a record. Delete an employee record.

With Jakarta Persistence, CRUD operations can be performed through an EntityManager. The following is an illustrative example that assumes a correctly configured persistence unit and an active transaction.

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

public class EmployeeExample {

    public static void main(String[] args) {
        EntityManagerFactory factory =
            Persistence.createEntityManagerFactory("employeePU");

        EntityManager entityManager = factory.createEntityManager();

        try {
            entityManager.getTransaction().begin();

            Employee employee =
                new Employee("Aarav Sharma",
                             "[email protected]",
                             45000.00);

            entityManager.persist(employee);
            entityManager.getTransaction().commit();

            Employee found =
                entityManager.find(Employee.class, employee.getId());

            System.out.println(found.getName());

        } catch (RuntimeException exception) {
            if (entityManager.getTransaction().isActive()) {
                entityManager.getTransaction().rollback();
            }
            throw exception;
        } finally {
            entityManager.close();
            factory.close();
        }
    }
}

Important: This example assumes that the Employee entity and the persistence unit named employeePU are configured correctly, the required database driver and persistence provider are present, and the database is available. A real application should also use appropriate logging and exception handling.

14. Entity Relationships in ORM

Applications often store related information in multiple tables. ORM supports mapping these relationships to object references and collections.

Relationship Description Example
One-to-One One entity is associated with one other entity. Person and passport
One-to-Many One entity is associated with multiple entities. Department and employees
Many-to-One Multiple entities refer to one entity. Many employees belong to one department
Many-to-Many Multiple entities can be associated with multiple others. Students and courses

Jakarta Persistence provides annotations such as @OneToOne, @OneToMany, @ManyToOne, and @ManyToMany. Relationship ownership, join columns, cascade behavior, and fetch settings should be selected carefully.

Example: Many Employees Belong to One Department

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.JoinColumn;

@Entity
public class Employee {

    @Id
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;

    public Employee() {
    }
}

In this example, each Employee can reference a Department. The department_id foreign-key column identifies the associated department. The Department entity must also be defined and mapped.

15. ORM and JDBC: Key Differences

JDBC is a Java API for connecting to databases and executing SQL. ORM frameworks commonly use JDBC internally for relational database communication while offering a higher-level object-oriented persistence model.

JDBC ORM
Developers commonly write SQL and process result sets manually. Common entity operations can be expressed through objects and persistence APIs.
Mapping query results to Java objects is usually explicit application code. Entity mapping and result conversion are handled by the ORM provider for supported operations.
Provides direct control over SQL execution. Provides abstraction for entity persistence and relationships.
Can be straightforward for small, SQL-focused tasks. Can reduce repetitive persistence code in object-oriented applications.
SQL and database-specific behavior are visible to the developer. Some SQL is generated automatically, but SQL knowledge remains important.

ORM does not make JDBC knowledge unnecessary. Understanding SQL, joins, indexes, transactions, and query execution plans is valuable for writing efficient Java applications.

16. Advantages of ORM

  • Reduced boilerplate: Common data-access operations require less repetitive code.
  • Object-oriented development: Developers work with entity classes and relationships.
  • Centralized mapping: Mapping metadata describes how application data corresponds to database structures.
  • Relationship management: Related entities can be represented through object references and collections.
  • Transaction integration: ORM operations can participate in database transactions.
  • Query support: Many ORM tools provide object-oriented query languages and criteria APIs.
  • Potential portability: Standard APIs and suitable mappings can make migration between supported databases easier.
  • Performance features: Caching, batching, and configurable fetching may improve performance when used appropriately.
  • Maintainability: Reusable mappings and persistence conventions can simplify application maintenance.

17. Limitations of ORM

ORM is useful, but it is not the best choice for every database task. Developers need to understand its behavior and monitor the SQL it produces.

  • Learning curve: Entity states, relationships, transactions, and fetching strategies require practice.
  • Hidden SQL: Automatic query generation can make inefficient database access less obvious.
  • Performance overhead: Mapping, tracking, and framework operations can introduce overhead.
  • N+1 query problem: Loading a collection and then retrieving each related record separately may cause many queries.
  • Complex SQL requirements: Reports and specialized queries may be easier to implement with native SQL or direct JDBC.
  • Mapping complexity: Inheritance, composite keys, and complex relationships can require careful configuration.
  • Database-specific behavior: Differences in SQL dialects and database features can affect portability.

18. ORM Performance Best Practices

  • Inspect generated SQL during development.
  • Use appropriate indexes based on actual query patterns.
  • Choose eager and lazy fetching deliberately.
  • Watch for N+1 queries and use suitable joins, entity graphs, or batch fetching where appropriate.
  • Retrieve only the data required by the application.
  • Use pagination for large result sets.
  • Use transactions to group related database operations.
  • Consider JDBC batching or ORM batch settings for large insert and update workloads.
  • Use projections or DTOs for read-only screens that do not need complete managed entities.
  • Measure performance with representative data instead of relying on assumptions.

19. ORM and Database Transactions

A database transaction groups related operations into a unit of work. Transactions are commonly described using ACID properties: Atomicity, Consistency, Isolation, and Durability.

ORM operations are often performed inside transactions so that related changes can be committed together or rolled back if an operation fails. The exact transaction API depends on the application environment.

Typical Transaction Workflow

  1. Begin a transaction.
  2. Load or create the required entities.
  3. Apply changes to the entities.
  4. Commit the transaction if the operations succeed.
  5. Roll back the transaction when appropriate if an error occurs.

In managed environments, such as applications using a framework or Jakarta EE container, transactions may be managed declaratively. Follow the transaction-management approach configured for the application.

20. ORM Security Considerations

ORM does not automatically make an application secure. Developers must still validate input, protect database credentials, configure permissions, and use queries safely.

  • Use parameterized queries or safe query APIs instead of concatenating untrusted input into SQL.
  • Validate and authorize user actions before modifying persistent records.
  • Use least-privilege database accounts.
  • Keep database credentials out of source code and public repositories.
  • Avoid logging passwords, access tokens, or unnecessary personal information.
  • Review generated SQL and database access patterns for unintended data exposure.
  • Use transactions and constraints to protect data integrity.

21. Common ORM Mistakes and Troubleshooting

Problem Possible Cause Recommended Check
Entity is not recognized Missing entity annotation or incorrect persistence configuration Verify entity registration and package scanning.
Primary-key error Missing identifier mapping or incompatible generation strategy Check the identifier annotation and database schema.
Data is not saved Transaction not committed or persistence operation not performed Review transaction boundaries and provider logs.
Column or table not found Mapping names do not match the schema Verify table and column names and naming strategies.
Unexpected duplicate records Application logic or transaction handling permits repeated inserts Review entity creation logic and database constraints.
Slow queries Missing indexes, excessive fetching, or inefficient generated SQL Inspect SQL, execution plans, and query counts.
Lazy-loading exception A lazy relationship is accessed after its persistence context is closed Load required data within a suitable transaction or use an appropriate fetch plan.
Too many queries N+1 query behavior or repeated database access Review relationship fetching and batch-loading options.

22. Practical Example: Employee Management Application

Consider an Employee Management System that stores employee details in a relational database. The application should allow users to register employees, view employee details, update salaries, and remove records when authorized.

Suggested Entity Fields

  • Employee ID
  • Employee Name
  • Email Address
  • Department
  • Salary

Suggested Development Steps

  1. Create the Java project and add a compatible Jakarta Persistence provider, such as Hibernate ORM.
  2. Add the JDBC driver for the selected relational database.
  3. Configure the database connection and persistence unit.
  4. Create an Employee entity with an identifier and mapped fields.
  5. Configure schema management or use a database migration tool.
  6. Implement create, read, update, and delete operations.
  7. Use transactions for data-changing operations.
  8. Test successful operations, invalid inputs, and database failures.
  9. Inspect generated SQL and verify database performance.

23. Best Practices for Beginners

  • Learn SQL and JDBC fundamentals before relying entirely on ORM.
  • Use clear entity and field names.
  • Define primary keys and constraints correctly.
  • Use BigDecimal instead of floating-point types for precise monetary values.
  • Keep transaction boundaries clear.
  • Understand the difference between transient, managed, detached, and removed entity states.
  • Do not expose internal entity objects directly from every application API; consider DTOs when appropriate.
  • Use database migrations for controlled schema changes in shared or production environments.
  • Test mappings and relationships with the actual database technology where practical.
  • Keep ORM provider versions and dependencies compatible with the Java and Jakarta Persistence versions used by the project.

24. Practice Exercises

  1. Explain ORM in your own words and describe why Java applications use it.
  2. Create a Student entity with an ID, name, email, and course name.
  3. Map a Java class to a database table using @Entity and @Table.
  4. Use @Id and a suitable identifier-generation strategy.
  5. Implement a basic operation that saves an entity inside a transaction.
  6. Retrieve an entity by its primary key using EntityManager.find().
  7. Compare direct JDBC data access with ORM-based entity persistence.
  8. Design a Department and Employee relationship using @ManyToOne.
  9. Investigate a slow query and identify whether fetching behavior or indexing could be responsible.
  10. Explain how a transaction can protect a group of related changes.

25. Interview Questions and Answers

Q1. What is ORM?

Answer: ORM is a technique that maps object-oriented program structures, such as Java classes and objects, to relational database structures, such as tables and rows.

Q2. Why is ORM used in Java?

Answer: ORM reduces repetitive database-access code, maps records to objects, supports relationships, and provides APIs for common persistence operations.

Q3. What is an entity?

Answer: An entity is a Java class whose instances represent persistent data managed through a persistence provider. In Jakarta Persistence, the class is typically marked with @Entity.

Q4. What is Hibernate?

Answer: Hibernate ORM is a Java ORM framework that maps Java objects to relational database structures. It can be used through its native APIs or as an implementation of Jakarta Persistence.

Q5. What is JPA?

Answer: JPA, now known as Jakarta Persistence, is a specification that defines standard APIs and mapping annotations for persistence in Java applications.

Q6. Is JPA an implementation?

Answer: No. Jakarta Persistence defines the specification and APIs. A provider such as Hibernate or EclipseLink implements them.

Q7. What is the difference between ORM and JDBC?

Answer: JDBC is a lower-level Java database API that allows direct SQL execution. ORM provides a higher-level object-persistence model and commonly uses JDBC internally.

Q8. What is a primary key in ORM?

Answer: It is the identifier that uniquely identifies an entity record in the database. In Jakarta Persistence, the identifier is commonly marked using @Id.

Q9. What are CRUD operations?

Answer: CRUD stands for Create, Read, Update, and Delete. These are the basic operations used to manage persistent data.

Q10. What is the N+1 query problem?

Answer: It occurs when an initial query loads a collection of records and additional queries are executed for related data for each record. Suitable fetching strategies and query design can reduce this problem.

Q11. Does ORM eliminate the need to learn SQL?

Answer: No. SQL knowledge remains essential for understanding generated queries, optimizing performance, designing schemas, and troubleshooting database issues.

Q12. What is persistence?

Answer: Persistence is the ability to store data so it remains available beyond the lifetime of the current application process.

26. Quick Revision

  • ORM stands for Object-Relational Mapping.
  • ORM connects Java objects with relational database structures.
  • A Java class can represent a table, and an entity instance can represent a row.
  • Entity fields map to database columns.
  • @Entity marks a persistent entity class.
  • @Id identifies the primary key.
  • Jakarta Persistence defines standard persistence APIs; Hibernate ORM is one implementation.
  • CRUD means Create, Read, Update, and Delete.
  • ORM supports entity relationships and can coordinate changes through transactions.
  • ORM reduces repetitive code but does not remove the need for SQL knowledge.
  • Generated SQL, transaction boundaries, and fetching behavior should be reviewed for correctness and performance.

27. Conclusion

Object-Relational Mapping is an important concept in Advanced Java because it helps developers work with relational data through Java objects. By mapping classes, fields, identifiers, and relationships to database structures, ORM frameworks reduce repetitive persistence code and provide a consistent way to manage application data.

Understanding ORM fundamentals prepares developers to work with Hibernate ORM and Jakarta Persistence in real-world applications. Effective use of ORM also requires knowledge of SQL, database design, transaction management, security, and performance optimization.

Learn More with JustAcademy

Explore the Advanced Java Training Course to continue learning Java persistence and enterprise application development.

Interested in learning more? Register for a Course Demo or visit the JustAcademy website.

Previous Next
whatsapp