SHA256
Запрос для работы с параметрами пользователя работают!! И тесты на них проходят!!
177 lines
6.2 KiB
Java
177 lines
6.2 KiB
Java
package shine.db.dao;
|
|
|
|
import shine.db.SqliteDbController;
|
|
import shine.db.entities.UserParamEntry;
|
|
|
|
import java.sql.*;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* UserParamsDAO — хранение сохранённых параметров пользователя.
|
|
*
|
|
* Правило:
|
|
* - методы с Connection НЕ закрывают соединение
|
|
* - методы без Connection сами открывают и закрывают соединение
|
|
*
|
|
* ЛОГИКА time_ms:
|
|
* - БД принимает запись только если она "новее" (time_ms строго больше текущего).
|
|
* - Реализовано атомарно одним SQL: UPSERT + WHERE users_params.time_ms < excluded.time_ms
|
|
*
|
|
* Возврат результата:
|
|
* - upsertIfNewer(...) возвращает количество изменённых строк:
|
|
* 1 = вставили/обновили
|
|
* 0 = проигнорировали (запись уже новее или равная)
|
|
*/
|
|
public final class UserParamsDAO {
|
|
|
|
private static volatile UserParamsDAO instance;
|
|
private final SqliteDbController db = SqliteDbController.getInstance();
|
|
|
|
private UserParamsDAO() { }
|
|
|
|
public static UserParamsDAO getInstance() {
|
|
if (instance == null) {
|
|
synchronized (UserParamsDAO.class) {
|
|
if (instance == null) instance = new UserParamsDAO();
|
|
}
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
// -------------------- UPSERT (IF NEWER) --------------------
|
|
|
|
/**
|
|
* Атомарный UPSERT "только если новее".
|
|
*
|
|
* @return 1 если вставили/обновили; 0 если запись не тронули (existing.time_ms >= incoming.time_ms).
|
|
*/
|
|
public int upsertIfNewer(Connection c, UserParamEntry e) throws SQLException {
|
|
String sql = """
|
|
INSERT INTO users_params (
|
|
login,
|
|
param,
|
|
time_ms,
|
|
value,
|
|
device_key,
|
|
signature
|
|
) VALUES (?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(login, param)
|
|
DO UPDATE SET
|
|
time_ms = excluded.time_ms,
|
|
value = excluded.value,
|
|
device_key = excluded.device_key,
|
|
signature = excluded.signature
|
|
WHERE users_params.time_ms < excluded.time_ms
|
|
""";
|
|
|
|
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
|
ps.setString(1, e.getLogin());
|
|
ps.setString(2, e.getParam());
|
|
ps.setLong(3, e.getTimeMs());
|
|
ps.setString(4, e.getValue());
|
|
|
|
if (e.getDeviceKey() != null) ps.setString(5, e.getDeviceKey());
|
|
else ps.setNull(5, Types.VARCHAR);
|
|
|
|
if (e.getSignature() != null) ps.setString(6, e.getSignature());
|
|
else ps.setNull(6, Types.VARCHAR);
|
|
|
|
return ps.executeUpdate(); // 1 или 0
|
|
}
|
|
}
|
|
|
|
/** То же самое, но сам открывает/закрывает соединение. */
|
|
public int upsertIfNewer(UserParamEntry e) throws SQLException {
|
|
try (Connection c = db.getConnection()) {
|
|
return upsertIfNewer(c, e);
|
|
}
|
|
}
|
|
|
|
// -------------------- SELECT --------------------
|
|
|
|
/** Получить параметр по (login,param) с внешним соединением. Соединение НЕ закрывает. */
|
|
public UserParamEntry getByLoginAndParam(Connection c, String login, String param) throws SQLException {
|
|
String sql = """
|
|
SELECT
|
|
login,
|
|
param,
|
|
time_ms,
|
|
value,
|
|
device_key,
|
|
signature
|
|
FROM users_params
|
|
WHERE login = ? AND param = ?
|
|
LIMIT 1
|
|
""";
|
|
|
|
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
|
ps.setString(1, login);
|
|
ps.setString(2, param);
|
|
|
|
try (ResultSet rs = ps.executeQuery()) {
|
|
if (!rs.next()) return null;
|
|
return mapRow(rs);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Получить параметр по (login,param) без внешнего соединения. Сам открывает/закрывает. */
|
|
public UserParamEntry getByLoginAndParam(String login, String param) throws SQLException {
|
|
try (Connection c = db.getConnection()) {
|
|
return getByLoginAndParam(c, login, param);
|
|
}
|
|
}
|
|
|
|
/** Получить все параметры пользователя с внешним соединением. */
|
|
public List<UserParamEntry> getByLogin(Connection c, String login) throws SQLException {
|
|
String sql = """
|
|
SELECT
|
|
login,
|
|
param,
|
|
time_ms,
|
|
value,
|
|
device_key,
|
|
signature
|
|
FROM users_params
|
|
WHERE login = ?
|
|
ORDER BY time_ms DESC
|
|
""";
|
|
|
|
List<UserParamEntry> list = new ArrayList<>();
|
|
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
|
ps.setString(1, login);
|
|
try (ResultSet rs = ps.executeQuery()) {
|
|
while (rs.next()) list.add(mapRow(rs));
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/** Получить все параметры пользователя без внешнего соединения. */
|
|
public List<UserParamEntry> getByLogin(String login) throws SQLException {
|
|
try (Connection c = db.getConnection()) {
|
|
return getByLogin(c, login);
|
|
}
|
|
}
|
|
|
|
// -------------------- MAPPER --------------------
|
|
|
|
private static UserParamEntry mapRow(ResultSet rs) throws SQLException {
|
|
UserParamEntry e = new UserParamEntry();
|
|
e.setLogin(rs.getString("login"));
|
|
e.setParam(rs.getString("param"));
|
|
e.setTimeMs(rs.getLong("time_ms"));
|
|
e.setValue(rs.getString("value"));
|
|
|
|
String dk = rs.getString("device_key");
|
|
if (rs.wasNull()) dk = null;
|
|
e.setDeviceKey(dk);
|
|
|
|
String sig = rs.getString("signature");
|
|
if (rs.wasNull()) sig = null;
|
|
e.setSignature(sig);
|
|
|
|
return e;
|
|
}
|
|
} |