package com.rosetta.im.database; import java.util.HashMap; import java.util.List; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.query.Query; /** * Базовый репозиторий для работы с сущностями базы данных */ public abstract class Repository { protected Class entityClass; public Repository(Class entityClass) { this.entityClass = entityClass; } /** * Сохранение сущности в базе данных * @param entity сущность для сохранения * @return сохраненная сущность */ public T save(T entity) { return executeInTransaction(session -> { session.persist(entity); return entity; }); } /** * Обновление сущности в базе данных * @param entity сущность для обновления * @return обновленная сущность */ public T update(T entity) { return executeInTransaction(session -> { session.merge(entity); return entity; }); } /** * Удаление сущности из базы данных * @param entity сущность для удаления */ public void delete(T entity) { executeInTransaction(session -> { session.remove(entity); return null; }); } /** * Поиск сущности по значению одного поля * @param fieldName поле * @param value значение * @return найденная сущность или null */ public T findByField(String fieldName, Object value) { return executeInSession(session -> { String queryString = "FROM " + entityClass.getSimpleName() + " WHERE " + fieldName + " = :value"; return session.createQuery(queryString, entityClass) .setParameter("value", value) .uniqueResult(); }); } /** * Поиск сущности по значению одного поля с использованием оператора LIKE * @param fieldName поле * @param value значение * @return найденная сущность или null */ public T likeSearch(String fieldName, String value) { return executeInSession(session -> { String queryString = "FROM " + entityClass.getSimpleName() + " WHERE " + fieldName + " LIKE :value"; return session.createQuery(queryString, entityClass) .setParameter("value", "%" + value + "%") .uniqueResult(); }); } /** * Поиск сущности по значению одного поля с использованием оператора LIKE * @param fieldName поле * @param value значение * @return найденная сущность или null */ public List likeSearchAll(String fieldName, String value) { return executeInSession(session -> { String queryString = "FROM " + entityClass.getSimpleName() + " WHERE " + fieldName + " LIKE :value"; return session.createQuery(queryString, entityClass) .setParameter("value", value + "%") .list(); }); } /** * Поиск сущности по значению одного поля с использованием оператора LIKE и ограничения LIMIT * @param fieldName поле * @param value значение * @return найденная сущность или null */ public List likeSearchAll(String fieldName, String value, int take) { return executeInSession(session -> { String queryString = "FROM " + entityClass.getSimpleName() + " WHERE " + fieldName + " LIKE :value"; return session.createQuery(queryString, entityClass) .setParameter("value", value + "%") .setMaxResults(take) .list(); }); } /** * Поиск сущности по набору полей * @param fields карта полей и их значений * @return найденная сущность или null */ public T findByField(HashMap fields) { return executeInSession(session -> { StringBuilder queryString = new StringBuilder("FROM " + entityClass.getSimpleName() + " WHERE "); int index = 0; for (String fieldName : fields.keySet()) { if (index > 0) { queryString.append(" AND "); } queryString.append(fieldName).append(" = :").append(fieldName); index++; } var query = session.createQuery(queryString.toString(), this.entityClass); for (var entry : fields.entrySet()) { query.setParameter(entry.getKey(), entry.getValue()); } return query.uniqueResult(); }); } /** * Удаление сущностей по значению одного поля * @param fieldName поле * @param value значение */ public void deleteByField(String fieldName, Object value) { executeInTransaction(session -> { String queryString = "DELETE FROM " + entityClass.getSimpleName() + " WHERE " + fieldName + " = :value"; session.createQuery(queryString, entityClass) .setParameter("value", value) .executeUpdate(); return null; }); } /** * Поиск всех сущностей по значению одного поля * @param fieldName поле * @param value значение * @return список найденных сущностей */ public List findAllByField(String fieldName, Object value) { return executeInSession(session -> { String queryString = "FROM " + entityClass.getSimpleName() + " WHERE " + fieldName + " = :value"; return session.createQuery(queryString, entityClass) .setParameter("value", value) .list(); }); } /** * Поиск всех сущностей по значению набора полей * @param fields карта полей и их значений * @return список найденных сущностей */ public List findAllByField(HashMap fields) { return executeInSession(session -> { StringBuilder queryString = new StringBuilder("FROM " + entityClass.getSimpleName() + " WHERE "); int index = 0; for (String fieldName : fields.keySet()) { if (index > 0) { queryString.append(" AND "); } queryString.append(fieldName).append(" = :").append(fieldName); index++; } var query = session.createQuery(queryString.toString(), this.entityClass); for (var entry : fields.entrySet()) { query.setParameter(entry.getKey(), entry.getValue()); } return query.list(); }); } /** * Поиск всех сущностей, тяжелый метод, лучше не выполнять без необходимости * @return список всех сущностей */ public List findAll() { return executeInSession(session -> { String queryString = "FROM " + entityClass.getSimpleName(); return session.createQuery(queryString, entityClass).list(); }); } /** * Подсчет всех сущностей в таблице * @return количество сущностей */ public long countAll() { return executeInSession(session -> { String queryString = "SELECT COUNT(*) FROM " + entityClass.getSimpleName(); return session.createQuery(queryString, Long.class).uniqueResult(); }); } /** * Подсчет сущностей по значению одного поля * @param fieldName поле * @param value значение * @return количество сущностей */ public long countByField(String fieldName, Object value) { return executeInSession(session -> { String queryString = "SELECT COUNT(*) FROM " + entityClass.getSimpleName() + " WHERE " + fieldName + " = :value"; return session.createQuery(queryString, Long.class) .setParameter("value", value) .uniqueResult(); }); } /** * Выполняет запрос с параметрами и возвращает список сущностей * @param queryString SQL запрос * @param parameters параметры запроса * @return список сущностей */ public QuerySession buildQuery(String queryString, HashMap parameters) { Session session = HibernateUtil.openSession(); try { Query query = session.createQuery(queryString, entityClass); for (var entry : parameters.entrySet()) { query.setParameter(entry.getKey(), entry.getValue()); } return new QuerySession<>(session, query); } catch (Exception e) { session.close(); throw e; } } /** * Подсчет сущностей по набору полей * @param fields карта полей и их значений * @return количество сущностей */ public long countByField(HashMap fields) { return executeInSession(session -> { StringBuilder queryString = new StringBuilder("SELECT COUNT(*) FROM " + entityClass.getSimpleName() + " WHERE "); int index = 0; for (String fieldName : fields.keySet()) { if (index > 0) { queryString.append(" AND "); } queryString.append(fieldName).append(" = :").append(fieldName); index++; } var query = session.createQuery(queryString.toString(), Long.class); for (var entry : fields.entrySet()) { query.setParameter(entry.getKey(), entry.getValue()); } return query.uniqueResult(); }); } /** * Обновление полей сущности по заданным условиям * @param fieldsToUpdate поля для обновления * @param whereFields условия для выбора сущностей */ public void update(HashMap fieldsToUpdate, HashMap whereFields) { executeInTransaction(session -> { StringBuilder queryString = new StringBuilder("UPDATE " + entityClass.getSimpleName() + " SET "); int index = 0; for (String fieldName : fieldsToUpdate.keySet()) { if (index > 0) { queryString.append(", "); } queryString.append(fieldName).append(" = :").append(fieldName); index++; } queryString.append(" WHERE "); index = 0; for (String fieldName : whereFields.keySet()) { if (index > 0) { queryString.append(" AND "); } /** * Добавляем префикс where_ к параметрам условия WHERE, * чтобы избежать конфликтов имен с параметрами SET */ queryString.append(fieldName).append(" = :where_").append(fieldName); index++; } var query = session.createQuery(queryString.toString(), this.entityClass); for (var entry : fieldsToUpdate.entrySet()) { query.setParameter(entry.getKey(), entry.getValue()); } for (var entry : whereFields.entrySet()) { /** * Устанавливаем параметры с префиксом where_ для условий WHERE, * чтобы избежать конфликтов имен с параметрами SET */ query.setParameter("where_" + entry.getKey(), entry.getValue()); } query.executeUpdate(); return null; }); } protected R executeInTransaction(TransactionCallback callback) { Session session = HibernateUtil.openSession(); Transaction transaction = null; try { transaction = session.beginTransaction(); R result = callback.execute(session); transaction.commit(); return result; } catch (Exception e) { if (transaction != null) { transaction.rollback(); } throw new RuntimeException("Transaction failed: " + e.getMessage(), e); } finally { session.close(); } } protected R executeInSession(SessionCallback callback) { try (Session session = HibernateUtil.openSession()) { return callback.execute(session); } } /** * Функциональный интерфейс для обратного вызова транзакции. * (Коллбэки) */ @FunctionalInterface protected interface TransactionCallback { R execute(Session session); } @FunctionalInterface protected interface SessionCallback { R execute(Session session); } }