JDBC ResultSet Mapping vs JPA Criteria API
Replace manual JDBC ResultSet mapping with JPA's type-safe Criteria API for dynamic queries.
String sql = "SELECT * FROM users"
+ " WHERE status = ? AND age > ?";
try (Connection con = ds.getConnection();
PreparedStatement ps =
con.prepareStatement(sql)) {
ps.setString(1, status);
ps.setInt(2, minAge);
ResultSet rs = ps.executeQuery();
List<User> users = new ArrayList<>();
while (rs.next()) {
User u = new User();
u.setId(rs.getLong("id"));
u.setName(rs.getString("name"));
u.setAge(rs.getInt("age"));
users.add(u);
}
}
@PersistenceContext
EntityManager em;
public List<User> findActiveAboveAge(
String status, int minAge) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> cq =
cb.createQuery(User.class);
Root<User> root = cq.from(User.class);
cq.select(root).where(
cb.equal(root.get("status"), status),
cb.greaterThan(root.get("age"), minAge));
return em.createQuery(cq).getResultList();
}
Type-safe queries
The Criteria builder catches field name and type mismatches at compile time.
Automatic mapping
JPA maps result rows to entity objects — no manual column-by-column extraction.
Composable predicates
Dynamic where-clauses build cleanly with and(), or(), and reusable Predicate objects.
Widely available since Jakarta EE 8 / Java 11
Raw JDBC requires building SQL strings, setting parameters by index, and mapping each ResultSet column manually — a process that is error-prone and breaks silently when columns change. The JPA Criteria API builds queries programmatically using a type-safe builder pattern. Column names are validated against the entity model, result mapping is automatic, and complex dynamic queries compose cleanly without string concatenation.