В чем разница между JDBCTemplate и Criteria API?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между JdbcTemplate и Criteria API
Эти два подхода к работе с данными в Spring предоставляют разные уровни абстракции для взаимодействия с базой данных. Каждый имеет свои преимущества и недостатки.
JdbcTemplate — Low-Level обработка SQL
JdbcTemplate — это низкоуровневый инструмент Spring для работы с JDBC. Вы пишете сырой SQL и управляете параметрами вручную.
@Repository
public class UserRepository {
private final JdbcTemplate jdbcTemplate;
public UserRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public List<User> findByAge(int age) {
String sql = "SELECT * FROM users WHERE age > ?";
return jdbcTemplate.query(
sql,
new Object[]{age},
new UserRowMapper()
);
}
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(
sql,
new Object[]{id},
new UserRowMapper()
);
}
public void insert(User user) {
String sql = "INSERT INTO users (name, email, age) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, user.getName(), user.getEmail(), user.getAge());
}
}
// RowMapper для преобразования результатов
class UserRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
return new User(
rs.getLong("id"),
rs.getString("name"),
rs.getString("email"),
rs.getInt("age")
);
}
}
Характеристики JdbcTemplate:
- SQL-ориентированность: Вы полностью контролируете SQL
- Низкоуровневость: Нужно самому управлять параметрами и маппингом
- Быстрота: Минимальный overhead
- Опасность: SQL injection если не использовать параметризованные запросы
Criteria API — Object-Oriented запросы
Criteria API — это часть JPA, которая позволяет строить запросы программно, без сырого SQL.
@Repository
public class UserRepository {
private final EntityManager entityManager;
public UserRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<User> findByAge(int age) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
query.select(user)
.where(cb.greaterThan(user.get("age"), age));
return entityManager.createQuery(query).getResultList();
}
public List<User> findByAgeAndEmail(int age, String email) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
query.select(user)
.where(
cb.and(
cb.greaterThan(user.get("age"), age),
cb.like(user.get("email"), email + "%")
)
);
return entityManager.createQuery(query).getResultList();
}
public List<User> findSorted(int age) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
query.select(user)
.where(cb.greaterThan(user.get("age"), age))
.orderBy(cb.asc(user.get("name")));
return entityManager.createQuery(query).getResultList();
}
}
Характеристики Criteria API:
- Type-safety: Ошибки в имена полей ловятся при компиляции
- Dynamically built queries: Запросы строятся программно
- Reusability: Условия можно комбинировать
- Сложность: Более многословно, чем JPQL
Сравнение — Простой поиск
JdbcTemplate:
String sql = "SELECT * FROM users WHERE age > ? AND status = ?";
List<User> users = jdbcTemplate.query(
sql,
new Object[]{minAge, "ACTIVE"},
new UserRowMapper()
);
Criteria API:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
query.select(user)
.where(
cb.and(
cb.greaterThan(user.get("age"), minAge),
cb.equal(user.get("status"), "ACTIVE")
)
);
List<User> users = entityManager.createQuery(query).getResultList();
Сравнение — Сложный запрос
JdbcTemplate:
String sql = """
SELECT u.id, u.name, u.email, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.age > ? AND u.status = ?
GROUP BY u.id, u.name, u.email
HAVING COUNT(o.id) > ?
ORDER BY order_count DESC
""";
List<Map<String, Object>> results = jdbcTemplate.queryForList(
sql,
minAge, "ACTIVE", minOrders
);
Criteria API:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
Root<User> user = query.from(User.class);
Join<User, Order> orders = user.leftJoin("orders");
query.select(cb.array(
user.get("id"),
user.get("name"),
user.get("email"),
cb.count(orders.get("id"))
))
.where(
cb.and(
cb.greaterThan(user.get("age"), minAge),
cb.equal(user.get("status"), "ACTIVE")
)
)
.groupBy(user.get("id"), user.get("name"), user.get("email"))
.having(cb.greaterThan(cb.count(orders.get("id")), minOrders))
.orderBy(cb.desc(cb.count(orders.get("id"))));
List<Object[]> results = entityManager.createQuery(query).getResultList();
Преимущества и недостатки
JdbcTemplate:
- Преимущества: контроль, производительность, простота для простых запросов
- Недостатки: SQL injection (если не осторожный), код не type-safe, много boilerplate
Criteria API:
- Преимущества: type-safe, защита от SQL injection, reusable conditions, динамические запросы
- Недостатки: многословность, более сложный синтаксис, медленнее для простых запросов
Современная альтернатива — QueryDSL
@Repository
public class UserRepository {
private final JPAQueryFactory queryFactory;
public UserRepository(JPAQueryFactory queryFactory) {
this.queryFactory = queryFactory;
}
public List<User> findByAge(int age) {
return queryFactory
.selectFrom(QUser.user)
.where(QUser.user.age.gt(age))
.fetch();
}
public List<User> findByAgeAndStatus(int age, String status) {
return queryFactory
.selectFrom(QUser.user)
.where(
QUser.user.age.gt(age),
QUser.user.status.eq(status)
)
.orderBy(QUser.user.name.asc())
.fetch();
}
}
QueryDSL более читаемый и type-safe, чем Criteria API.
Когда что использовать
JdbcTemplate:
- Простые CRUD операции
- Высокопроизводительные запросы
- Сложный SQL с использованием специфических функций БД
Criteria API / QueryDSL:
- Динамические запросы, строящиеся программно
- Type-safe код
- Сложная бизнес-логика с множеством условий
Выводы
JdbcTemplate — это низкоуровневый инструмент для контролируемого управления SQL. Criteria API предоставляет объектно-ориентированный способ построения запросов. Выбор зависит от сложности запросов, требований к производительности и предпочтений разработчика. Для современных проектов часто используют QueryDSL как улучшенную альтернативу Criteria API.