Files
rosetta-wss/src/main/java/com/rosetta/im/database/Repository.java

361 lines
14 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<T> {
protected Class<T> entityClass;
public Repository(Class<T> 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<T> 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<T> 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<String, Object> 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<T> 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<T> findAllByField(HashMap<String, Object> 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<T> 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<T> buildQuery(String queryString, HashMap<String, Object> parameters) {
Session session = HibernateUtil.openSession();
try {
Query<T> 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<String, Object> 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<String, Object> fieldsToUpdate, HashMap<String, Object> 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> R executeInTransaction(TransactionCallback<R> 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> R executeInSession(SessionCallback<R> callback) {
try (Session session = HibernateUtil.openSession()) {
return callback.execute(session);
}
}
/**
* Функциональный интерфейс для обратного вызова транзакции.
* (Коллбэки)
*/
@FunctionalInterface
protected interface TransactionCallback<R> {
R execute(Session session);
}
@FunctionalInterface
protected interface SessionCallback<R> {
R execute(Session session);
}
}