Interacting with Databases in Java: JDBC, ORM, and JPA

A Database Management System (DBMS) is software used to store, manage, and retrieve data efficiently. Examples include MySQL, PostgreSQL, Oracle, MariaDB, and SQL Server. For decades, Java developers connected to these systems using raw SQL and the JDBC API, but as applications became more complex, the need for automation, object mapping, and data abstraction led to the rise of Object-Relational Mapping (ORM) frameworks and later the creation of the Java Persistence API (JPA) standard.


1. JDBC (Java Database Connectivity)

JDBC is the low-level Java API for interacting with relational databases. It provides explicit control over SQL execution, connection management, and result processing.

JDBC Core Example – Connecting, Inserting, Querying


// 1. OPEN a connection
String url = "jdbc:mysql://localhost:3306/school";
String user = "appuser";
String pass = "secret";

Connection conn = DriverManager.getConnection(url, user, pass);

// 2. INSERT example
String insert = "INSERT INTO student (name, YEAR) VALUES (?, ?)";
PreparedStatement stmt = conn.prepareStatement(INSERT);
stmt.setString(1, "Alice");
stmt.setInt(2, 2025);
stmt.executeUpdate();

// 3. Query example
String query = "SELECT id, name, YEAR FROM student WHERE year = ?";
PreparedStatement q = conn.prepareStatement(query);
q.setInt(1, 2025);

ResultSet rs = q.executeQuery();
while (rs.next()) {
    System.out.println(rs.getLong("id") + " " +
                       rs.getString("name") + " " +
                       rs.getInt("YEAR"));
}

JDBC Transaction Example


try {
    conn.setAutoCommit(false);

    PreparedStatement s1 = conn.prepareStatement(
        "UPDATE accounts SET balance = balance - 100 WHERE id = 1"
    );
    PreparedStatement s2 = conn.prepareStatement(
        "UPDATE accounts SET balance = balance + 100 WHERE id = 2"
    );

    s1.executeUpdate();
    s2.executeUpdate();

    conn.COMMIT();
} catch (Exception ex) {
    conn.ROLLBACK();
}

2. Object-Relational Mapping (ORM)

ORM frameworks map Java classes to database tables and Java objects to rows. Instead of writing SQL manually, developers work with objects. This reduces boilerplate, improves readability, and centralizes mappings, caching, transactions, and relationships.

Why ORM Exists

Simple ORM Example (Generic)


User u = new User();
u.setName("Bob");
u.setEmail("bob@example.com");

entityManager.persist(u);

The ORM generates SQL automatically:


INSERT INTO users (name, email) VALUES (?, ?);

3. JPA (Java Persistence API)

JPA is the standardized ORM API in Java. Hibernate, EclipseLink, and OpenJPA implement it. JPA provides annotations, entity management, JPQL querying, relationships, and lifecycle handling.

3.1 Basic JPA Entity


import jakarta.persistence.*;

@Entity
@Table(name = "student")
public class Student {

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

    private String name;
    private int year;

    // getters & setters
}

3.2 Persisting an Entity


EntityManager em = emf.createEntityManager();
em.getTransaction().BEGIN();

Student s = new Student();
s.setName("Alice");
s.setYear(2025);

em.persist(s);

em.getTransaction().COMMIT();
em.CLOSE();

3.3 JPQL Query


String jpql = "SELECT s FROM Student s WHERE s.year = :yr";

List<Student> list = em.createQuery(jpql, Student.class)
                         .setParameter("yr", 2025)
                         .getResultList();

4. Relationships in JPA

JPA supports one-to-one, one-to-many, many-to-one, and many-to-many mappings.

4.1 One-to-Many with Lazy Loading


@Entity
public class User {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
    private List<ORDER> orders = new ArrayList<>();
}

@Entity
public class Order {

    @Id @GeneratedValue
    private Long id;

    private double total;

    @ManyToOne
    private User user;
}

Lazy Load Behavior

Lazy relationships are not loaded until accessed.


User u = em.find(User.class, 1L);

// orders are NOT loaded yet

List<ORDER> orders = u.getOrders(); 
// Lazy loading triggers SELECT query here!

5. JPA Transaction Example


EntityManager em = emf.createEntityManager();

try {
    em.getTransaction().BEGIN();

    Account a = em.find(Account.class, 1L);
    Account b = em.find(Account.class, 2L);

    a.withdraw(100);
    b.deposit(100);

    em.getTransaction().COMMIT();
} catch (Exception e) {
    em.getTransaction().ROLLBACK();
}

6. Spring Data JPA Repository Example


public interface StudentRepository 
       extends JpaRepository<Student, Long> {

    List<Student> findByYear(int YEAR);
}

Spring Data automatically generates:


SELECT * FROM student WHERE year = ?;

7. What Happens Under the Hood (JPA/Hibernate)


8. When to Use JDBC vs ORM vs JPA

å
Feature JDBC ORM JPA
SQL Control Full Medium Low
Boilerplate High Medium Low
Mapping No Yes Yes (standard)
Best Use High-performance, custom SQL General applications Enterprise / Spring apps