JDBC and Persistence in Java
JDBC basics
JDBC is the standard API for talking to relational databases.
import java.sql.*;
import java.util.*;
public class NoteDao {
private final javax.sql.DataSource ds;
public NoteDao(javax.sql.DataSource ds) { this.ds = ds; }
public long insert(long userId, String text) throws SQLException {
String sql = "INSERT INTO notes (user_id, text) VALUES (?, ?)";
try (Connection c = ds.getConnection();
PreparedStatement ps = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
ps.setLong(1, userId);
ps.setString(2, text);
ps.executeUpdate();
try (ResultSet keys = ps.getGeneratedKeys()) {
keys.next();
return keys.getLong(1);
}
}
}
public List<String> list(long userId) throws SQLException {
String sql = "SELECT text FROM notes WHERE user_id = ? ORDER BY id DESC";
List<String> out = new ArrayList<>();
try (Connection c = ds.getConnection();
PreparedStatement ps = c.prepareStatement(sql)) {
ps.setLong(1, userId);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) out.add(rs.getString("text"));
}
}
return out;
}
}
CAUTION
Always use PreparedStatement with placeholders. Building SQL by string concatenation causes SQL injection.
Transactions
try (Connection c = ds.getConnection()) {
c.setAutoCommit(false);
try {
debit(c, fromId, amount);
credit(c, toId, amount);
c.commit();
} catch (SQLException e) {
c.rollback();
throw e;
}
}
See Transactions and concurrency for ACID and isolation levels.
Connection pooling
Opening connections is expensive. Use a pool such as HikariCP.
HikariConfig cfg = new HikariConfig();
cfg.setJdbcUrl(System.getenv("DATABASE_URL"));
cfg.setMaximumPoolSize(10);
DataSource ds = new HikariDataSource(cfg);
JPA and Hibernate
JPA maps classes to tables so you work with objects.
import jakarta.persistence.*;
@Entity
@Table(name = "notes")
public class Note {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 500)
private String text;
// getters and setters
}
| JDBC | JPA / Hibernate |
|---|---|
| Full control of SQL | Productivity, object mapping |
| More boilerplate | Risk of N+1 queries and surprising SQL |
| Good for reports and hot paths | Good for typical CRUD |
Know both: use JPA for CRUD and drop to SQL for complex queries.