From d6d2bfeb739d531c149588c9dcebde95e11945a7960b40940860ae17af2b3256 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Thu, 18 Dec 2025 15:58:43 +0300 Subject: [PATCH] =?UTF-8?q?19=2012=2025=20=D0=92=D1=81=D0=B5=20=D0=94?= =?UTF-8?q?=D0=90=D0=9E=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B8=D0=BB=D0=B8?= =?UTF-8?q?=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D1=8B=D0=B9=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D1=82=D0=BE=D0=B3=D0=BE=20=D1=87=D1=82?= =?UTF-8?q?=D0=BE=20=D0=B1=D1=8B=20=D0=B2=D1=8B=D0=B7=D1=8B=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=D1=81=D1=8F=20=D1=81=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=D0=B0=D1=87=D0=B5=D0=B9=20=D1=81=D0=BE=D0=B5=D0=B4=D0=B8?= =?UTF-8?q?=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D0=B1=D0=B5=D0=B7=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B0=D1=87=D0=B8=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B5=D0=B4=D0=B8=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/shine/db/dao/ActiveSessionsDAO.java | 107 +++++++++++++----- .../java/shine/db/dao/BlockchainStateDAO.java | 6 +- .../main/java/shine/db/dao/IpGeoCacheDAO.java | 86 ++++++++------ .../java/shine/db/dao/SolanaUsersDAO.java | 83 ++++++++------ .../main/java/shine/db/dao/UserParamsDAO.java | 68 ++++++----- ...вка по DAO. Правило перегруженных методов.txt | 27 +++++ 6 files changed, 250 insertions(+), 127 deletions(-) create mode 100644 shine-server-db/src/main/java/shine/db/dao/справка по DAO. Правило перегруженных методов.txt diff --git a/shine-server-db/src/main/java/shine/db/dao/ActiveSessionsDAO.java b/shine-server-db/src/main/java/shine/db/dao/ActiveSessionsDAO.java index 225a2db..54fff6c 100644 --- a/shine-server-db/src/main/java/shine/db/dao/ActiveSessionsDAO.java +++ b/shine-server-db/src/main/java/shine/db/dao/ActiveSessionsDAO.java @@ -9,6 +9,10 @@ import java.util.List; /** * DAO для таблицы active_sessions. + * + * Правило: + * - методы с Connection НЕ закрывают соединение + * - методы без Connection сами открывают и закрывают соединение */ public final class ActiveSessionsDAO { @@ -26,7 +30,10 @@ public final class ActiveSessionsDAO { return instance; } - public void insert(ActiveSessionEntry session) throws SQLException { + // -------------------- INSERT -------------------- + + /** Вставка с внешним соединением. Соединение НЕ закрывает. */ + public void insert(Connection c, ActiveSessionEntry session) throws SQLException { String sql = """ INSERT INTO active_sessions ( sessionId, @@ -45,9 +52,7 @@ public final class ActiveSessionsDAO { ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setString(1, session.getSessionId()); ps.setLong(2, session.getLoginId()); ps.setString(3, session.getSessionPwd()); @@ -61,12 +66,21 @@ public final class ActiveSessionsDAO { ps.setString(11, session.getClientInfoFromClient()); ps.setString(12, session.getClientInfoFromRequest()); ps.setString(13, session.getUserLanguage()); - ps.executeUpdate(); } } - public ActiveSessionEntry getBySessionId(String sessionId) throws SQLException { + /** Вставка без внешнего соединения. Сам открывает/закрывает. */ + public void insert(ActiveSessionEntry session) throws SQLException { + try (Connection c = db.getConnection()) { + insert(c, session); + } + } + + // -------------------- SELECT -------------------- + + /** Получить по sessionId с внешним соединением. Соединение НЕ закрывает. */ + public ActiveSessionEntry getBySessionId(Connection c, String sessionId) throws SQLException { String sql = """ SELECT sessionId, @@ -86,11 +100,8 @@ public final class ActiveSessionsDAO { WHERE sessionId = ? """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setString(1, sessionId); - try (ResultSet rs = ps.executeQuery()) { if (!rs.next()) return null; return mapRow(rs); @@ -98,7 +109,15 @@ public final class ActiveSessionsDAO { } } - public List getByLoginId(long loginId) throws SQLException { + /** Получить по sessionId без внешнего соединения. Сам открывает/закрывает. */ + public ActiveSessionEntry getBySessionId(String sessionId) throws SQLException { + try (Connection c = db.getConnection()) { + return getBySessionId(c, sessionId); + } + } + + /** Получить список по loginId с внешним соединением. Соединение НЕ закрывает. */ + public List getByLoginId(Connection c, long loginId) throws SQLException { String sql = """ SELECT sessionId, @@ -120,11 +139,8 @@ public final class ActiveSessionsDAO { List result = new ArrayList<>(); - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setLong(1, loginId); - try (ResultSet rs = ps.executeQuery()) { while (rs.next()) result.add(mapRow(rs)); } @@ -133,23 +149,40 @@ public final class ActiveSessionsDAO { return result; } - public void updateLastAuthirificatedAtMs(String sessionId, long lastAuthMs) throws SQLException { + /** Получить список по loginId без внешнего соединения. Сам открывает/закрывает. */ + public List getByLoginId(long loginId) throws SQLException { + try (Connection c = db.getConnection()) { + return getByLoginId(c, loginId); + } + } + + // -------------------- UPDATE -------------------- + + /** Обновить lastAuthirificatedAtMs с внешним соединением. Соединение НЕ закрывает. */ + public void updateLastAuthirificatedAtMs(Connection c, String sessionId, long lastAuthMs) throws SQLException { String sql = """ UPDATE active_sessions SET lastAuthirificatedAtMs = ? WHERE sessionId = ? """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setLong(1, lastAuthMs); ps.setString(2, sessionId); ps.executeUpdate(); } } + /** Обновить lastAuthirificatedAtMs без внешнего соединения. Сам открывает/закрывает. */ + public void updateLastAuthirificatedAtMs(String sessionId, long lastAuthMs) throws SQLException { + try (Connection c = db.getConnection()) { + updateLastAuthirificatedAtMs(c, sessionId, lastAuthMs); + } + } + + /** Обновить данные refresh с внешним соединением. Соединение НЕ закрывает. */ public void updateOnRefresh( + Connection c, String sessionId, long lastAuthMs, String clientIp, @@ -169,9 +202,7 @@ public final class ActiveSessionsDAO { WHERE sessionId = ? """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setLong(1, lastAuthMs); ps.setString(2, clientIp); ps.setString(3, clientInfoFromClient); @@ -182,17 +213,41 @@ public final class ActiveSessionsDAO { } } - public void deleteBySessionId(String sessionId) throws SQLException { + /** Обновить данные refresh без внешнего соединения. Сам открывает/закрывает. */ + public void updateOnRefresh( + String sessionId, + long lastAuthMs, + String clientIp, + String clientInfoFromClient, + String clientInfoFromRequest, + String userLanguage + ) throws SQLException { + try (Connection c = db.getConnection()) { + updateOnRefresh(c, sessionId, lastAuthMs, clientIp, clientInfoFromClient, clientInfoFromRequest, userLanguage); + } + } + + // -------------------- DELETE -------------------- + + /** Удалить по sessionId с внешним соединением. Соединение НЕ закрывает. */ + public void deleteBySessionId(Connection c, String sessionId) throws SQLException { String sql = "DELETE FROM active_sessions WHERE sessionId = ?"; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setString(1, sessionId); ps.executeUpdate(); } } + /** Удалить по sessionId без внешнего соединения. Сам открывает/закрывает. */ + public void deleteBySessionId(String sessionId) throws SQLException { + try (Connection c = db.getConnection()) { + deleteBySessionId(c, sessionId); + } + } + + // -------------------- MAPPER -------------------- + private ActiveSessionEntry mapRow(ResultSet rs) throws SQLException { String sessionId = rs.getString("sessionId"); long loginId = rs.getLong("loginId"); diff --git a/shine-server-db/src/main/java/shine/db/dao/BlockchainStateDAO.java b/shine-server-db/src/main/java/shine/db/dao/BlockchainStateDAO.java index e66841f..3dc88a0 100644 --- a/shine-server-db/src/main/java/shine/db/dao/BlockchainStateDAO.java +++ b/shine-server-db/src/main/java/shine/db/dao/BlockchainStateDAO.java @@ -21,12 +21,14 @@ public final class BlockchainStateDAO { return instance; } + /** Получить по blockchainId без внешнего соединения. Сам открывает/закрывает. */ public BlockchainStateEntry getByBlockchainId(long blockchainId) throws SQLException { try (Connection c = db.getConnection()) { return getByBlockchainId(c, blockchainId); } } + /** Получить по blockchainId с внешним соединением. Соединение НЕ закрывает. */ public BlockchainStateEntry getByBlockchainId(Connection c, long blockchainId) throws SQLException { String sql = """ SELECT @@ -60,12 +62,14 @@ public final class BlockchainStateDAO { } } + /** UPSERT без внешнего соединения. Сам открывает/закрывает. */ public void upsert(BlockchainStateEntry e) throws SQLException { try (Connection c = db.getConnection()) { upsert(c, e); } } + /** UPSERT с внешним соединением. Соединение НЕ закрывает. */ public void upsert(Connection c, BlockchainStateEntry e) throws SQLException { String sql = """ INSERT INTO blockchain_state ( @@ -87,7 +91,7 @@ public final class BlockchainStateDAO { line7_last_number, line7_last_hash, updated_at_ms ) VALUES ( - ?,?,?,?,?,?,?,?, -- ✅ было 7, стало 8 + ?,?,?,?,?,?,?,?, ?,?, ?,?, ?,?, diff --git a/shine-server-db/src/main/java/shine/db/dao/IpGeoCacheDAO.java b/shine-server-db/src/main/java/shine/db/dao/IpGeoCacheDAO.java index 578c301..a4f7532 100644 --- a/shine-server-db/src/main/java/shine/db/dao/IpGeoCacheDAO.java +++ b/shine-server-db/src/main/java/shine/db/dao/IpGeoCacheDAO.java @@ -8,36 +8,35 @@ import java.sql.*; /** * DAO для таблицы ip_geo_cache. * - * Таблица: - * - ip TEXT PRIMARY KEY - * - geo TEXT - * - updated_at_ms INTEGER NOT NULL + * * Таблица: + * * - ip TEXT PRIMARY KEY + * * - geo TEXT + * * - updated_at_ms INTEGER NOT NULL + * + * Правило: + * - методы с Connection НЕ закрывают соединение + * - методы без Connection сами открывают и закрывают соединение */ public final class IpGeoCacheDAO { private static volatile IpGeoCacheDAO instance; private final SqliteDbController db = SqliteDbController.getInstance(); - private IpGeoCacheDAO() { - } + private IpGeoCacheDAO() { } public static IpGeoCacheDAO getInstance() { if (instance == null) { synchronized (IpGeoCacheDAO.class) { - if (instance == null) { - instance = new IpGeoCacheDAO(); - } + if (instance == null) instance = new IpGeoCacheDAO(); } } return instance; } - /** - * UPSERT по ip. - * Если записи нет — вставляем. - * Если есть — обновляем geo и updated_at_ms. - */ - public void upsert(IpGeoCacheEntry entry) throws SQLException { + // -------------------- UPSERT -------------------- + + /** UPSERT с внешним соединением. Соединение НЕ закрывает. */ + public void upsert(Connection c, IpGeoCacheEntry entry) throws SQLException { String sql = """ INSERT INTO ip_geo_cache (ip, geo, updated_at_ms) VALUES (?, ?, ?) @@ -47,9 +46,7 @@ public final class IpGeoCacheDAO { updated_at_ms = excluded.updated_at_ms """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setString(1, entry.getIp()); ps.setString(2, entry.getGeo()); ps.setLong(3, entry.getUpdatedAtMs()); @@ -57,45 +54,60 @@ public final class IpGeoCacheDAO { } } - /** - * Получить запись по IP. - * Если нет — возвращает null. - */ - public IpGeoCacheEntry getByIp(String ip) throws SQLException { + /** UPSERT без внешнего соединения. Сам открывает/закрывает. */ + public void upsert(IpGeoCacheEntry entry) throws SQLException { + try (Connection c = db.getConnection()) { + upsert(c, entry); + } + } + + // -------------------- SELECT -------------------- + + /** Получить по IP с внешним соединением. Соединение НЕ закрывает. */ + public IpGeoCacheEntry getByIp(Connection c, String ip) throws SQLException { String sql = """ SELECT ip, geo, updated_at_ms FROM ip_geo_cache WHERE ip = ? """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setString(1, ip); try (ResultSet rs = ps.executeQuery()) { - if (!rs.next()) { - return null; - } + if (!rs.next()) return null; return mapRow(rs); } } } - /** - * Опционально — очистка старых записей. - * Можно вызывать по расписанию, если нужно. - */ - public int deleteOlderThan(long thresholdMs) throws SQLException { + /** Получить по IP без внешнего соединения. Сам открывает/закрывает. */ + public IpGeoCacheEntry getByIp(String ip) throws SQLException { + try (Connection c = db.getConnection()) { + return getByIp(c, ip); + } + } + + // -------------------- DELETE -------------------- + + /** Удалить старые записи с внешним соединением. Соединение НЕ закрывает. */ + public int deleteOlderThan(Connection c, long thresholdMs) throws SQLException { String sql = "DELETE FROM ip_geo_cache WHERE updated_at_ms < ?"; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setLong(1, thresholdMs); return ps.executeUpdate(); } } + /** Удалить старые записи без внешнего соединения. Сам открывает/закрывает. */ + public int deleteOlderThan(long thresholdMs) throws SQLException { + try (Connection c = db.getConnection()) { + return deleteOlderThan(c, thresholdMs); + } + } + + // -------------------- MAPPER -------------------- + private IpGeoCacheEntry mapRow(ResultSet rs) throws SQLException { String ip = rs.getString("ip"); String geo = rs.getString("geo"); diff --git a/shine-server-db/src/main/java/shine/db/dao/SolanaUsersDAO.java b/shine-server-db/src/main/java/shine/db/dao/SolanaUsersDAO.java index 822bdad..d1a207a 100644 --- a/shine-server-db/src/main/java/shine/db/dao/SolanaUsersDAO.java +++ b/shine-server-db/src/main/java/shine/db/dao/SolanaUsersDAO.java @@ -17,6 +17,10 @@ import java.util.List; * - loginKey TEXT * - deviceKey TEXT * - bchLimit INTEGER (может быть NULL) + * + * * Правило: + * * - методы с Connection НЕ закрывают соединение + * * - методы без Connection сами открывают и закрывают соединение */ public final class SolanaUsersDAO { @@ -28,23 +32,22 @@ public final class SolanaUsersDAO { public static SolanaUsersDAO getInstance() { if (instance == null) { synchronized (SolanaUsersDAO.class) { - if (instance == null) { - instance = new SolanaUsersDAO(); - } + if (instance == null) instance = new SolanaUsersDAO(); } } return instance; } - public void insert(SolanaUserEntry user) throws SQLException { + // -------------------- INSERT -------------------- + + /** Вставка с внешним соединением. Соединение НЕ закрывает. */ + public void insert(Connection c, SolanaUserEntry user) throws SQLException { String sql = """ INSERT INTO solana_users (login, loginId, bchId, loginKey, deviceKey, bchLimit) VALUES (?, ?, ?, ?, ?, ?) """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setString(1, user.getLogin()); ps.setLong(2, user.getLoginId()); ps.setLong(3, user.getBchId()); @@ -61,16 +64,24 @@ public final class SolanaUsersDAO { } } - public SolanaUserEntry getByLoginId(long loginId) throws SQLException { + /** Вставка без внешнего соединения. Сам открывает/закрывает. */ + public void insert(SolanaUserEntry user) throws SQLException { + try (Connection c = db.getConnection()) { + insert(c, user); + } + } + + // -------------------- SELECT -------------------- + + /** Получить по loginId с внешним соединением. Соединение НЕ закрывает. */ + public SolanaUserEntry getByLoginId(Connection c, long loginId) throws SQLException { String sql = """ SELECT login, loginId, bchId, loginKey, deviceKey, bchLimit FROM solana_users WHERE loginId = ? """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setLong(1, loginId); try (ResultSet rs = ps.executeQuery()) { if (!rs.next()) return null; @@ -79,13 +90,20 @@ public final class SolanaUsersDAO { } } - // добавь рядом со старым методом + /** Получить по loginId без внешнего соединения. Сам открывает/закрывает. */ + public SolanaUserEntry getByLoginId(long loginId) throws SQLException { + try (Connection c = db.getConnection()) { + return getByLoginId(c, loginId); + } + } + + /** Получить по login (case-insensitive) с внешним соединением. Соединение НЕ закрывает. */ public SolanaUserEntry getByLogin(Connection c, String login) throws SQLException { String sql = """ - SELECT login, loginId, bchId, loginKey, deviceKey, bchLimit - FROM solana_users - WHERE LOWER(login) = LOWER(?) - """; + SELECT login, loginId, bchId, loginKey, deviceKey, bchLimit + FROM solana_users + WHERE LOWER(login) = LOWER(?) + """; try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setString(1, login); @@ -96,25 +114,15 @@ public final class SolanaUsersDAO { } } + /** Получить по login (case-insensitive) без внешнего соединения. Сам открывает/закрывает. */ public SolanaUserEntry getByLogin(String login) throws SQLException { - String sql = """ - SELECT login, loginId, bchId, loginKey, deviceKey, bchLimit - FROM solana_users - WHERE LOWER(login) = LOWER(?) - """; - - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - - ps.setString(1, login); - try (ResultSet rs = ps.executeQuery()) { - if (!rs.next()) return null; - return mapRow(rs); - } + try (Connection c = db.getConnection()) { + return getByLogin(c, login); } } - public List searchByLoginPrefix(String prefix) throws SQLException { + /** Поиск по префиксу с внешним соединением. Соединение НЕ закрывает. */ + public List searchByLoginPrefix(Connection c, String prefix) throws SQLException { String sql = """ SELECT login, loginId, bchId, loginKey, deviceKey, bchLimit FROM solana_users @@ -125,9 +133,7 @@ public final class SolanaUsersDAO { List result = new ArrayList<>(); - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setString(1, prefix.toLowerCase() + "%"); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) result.add(mapRow(rs)); @@ -137,6 +143,15 @@ public final class SolanaUsersDAO { return result; } + /** Поиск по префиксу без внешнего соединения. Сам открывает/закрывает. */ + public List searchByLoginPrefix(String prefix) throws SQLException { + try (Connection c = db.getConnection()) { + return searchByLoginPrefix(c, prefix); + } + } + + // -------------------- MAPPER -------------------- + private SolanaUserEntry mapRow(ResultSet rs) throws SQLException { return new SolanaUserEntry( rs.getLong("loginId"), diff --git a/shine-server-db/src/main/java/shine/db/dao/UserParamsDAO.java b/shine-server-db/src/main/java/shine/db/dao/UserParamsDAO.java index 59ea3e5..78e1e73 100644 --- a/shine-server-db/src/main/java/shine/db/dao/UserParamsDAO.java +++ b/shine-server-db/src/main/java/shine/db/dao/UserParamsDAO.java @@ -7,32 +7,27 @@ import java.sql.*; import java.util.ArrayList; import java.util.List; -/** Здесь зраним сохранённые параметры пользователей (в основном до каково сообщения просмотрены ленты) */ +/** Здесь храним сохранённые параметры пользователей (в основном до какого сообщения просмотрены ленты) */ public final class UserParamsDAO { private static volatile UserParamsDAO instance; private final SqliteDbController db = SqliteDbController.getInstance(); - private UserParamsDAO() { - } + private UserParamsDAO() { } public static UserParamsDAO getInstance() { if (instance == null) { synchronized (UserParamsDAO.class) { - if (instance == null) { - instance = new UserParamsDAO(); - } + if (instance == null) instance = new UserParamsDAO(); } } return instance; } - /** - * UPSERT методом ON CONFLICT — одним SQL-запросом. - * Если запись существует -> обновляем поля. - * Если нет -> вставляем новую запись. - */ - public void upsert(UserParamEntry param) throws SQLException { + // -------------------- UPSERT -------------------- + + /** UPSERT с внешним соединением. Соединение НЕ закрывает. */ + public void upsert(Connection c, UserParamEntry param) throws SQLException { String sql = """ INSERT INTO users_params ( loginId, @@ -52,9 +47,7 @@ public final class UserParamsDAO { signature = excluded.signature """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setLong(1, param.getLoginId()); ps.setString(2, param.getParam()); ps.setLong(3, param.getBchChannelId()); @@ -66,10 +59,17 @@ public final class UserParamsDAO { } } - /** - * Получить параметр по loginId + param. - */ - public UserParamEntry getByUserIdAndParam(long loginId, String paramName) throws SQLException { + /** UPSERT без внешнего соединения. Сам открывает/закрывает. */ + public void upsert(UserParamEntry param) throws SQLException { + try (Connection c = db.getConnection()) { + upsert(c, param); + } + } + + // -------------------- SELECT -------------------- + + /** Получить параметр с внешним соединением. Соединение НЕ закрывает. */ + public UserParamEntry getByUserIdAndParam(Connection c, long loginId, String paramName) throws SQLException { String sql = """ SELECT loginId, @@ -83,9 +83,7 @@ public final class UserParamsDAO { WHERE loginId = ? AND param = ? """; - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setLong(1, loginId); ps.setString(2, paramName); try (ResultSet rs = ps.executeQuery()) { @@ -95,10 +93,15 @@ public final class UserParamsDAO { } } - /** - * Получить все параметры пользователя. - */ - public List getByUserId(long loginId) throws SQLException { + /** Получить параметр без внешнего соединения. Сам открывает/закрывает. */ + public UserParamEntry getByUserIdAndParam(long loginId, String paramName) throws SQLException { + try (Connection c = db.getConnection()) { + return getByUserIdAndParam(c, loginId, paramName); + } + } + + /** Получить все параметры пользователя с внешним соединением. Соединение НЕ закрывает. */ + public List getByUserId(Connection c, long loginId) throws SQLException { String sql = """ SELECT loginId, @@ -115,9 +118,7 @@ public final class UserParamsDAO { List result = new ArrayList<>(); - try (Connection c = db.getConnection(); - PreparedStatement ps = c.prepareStatement(sql)) { - + try (PreparedStatement ps = c.prepareStatement(sql)) { ps.setLong(1, loginId); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) result.add(mapRow(rs)); @@ -127,6 +128,15 @@ public final class UserParamsDAO { return result; } + /** Получить все параметры пользователя без внешнего соединения. Сам открывает/закрывает. */ + public List getByUserId(long loginId) throws SQLException { + try (Connection c = db.getConnection()) { + return getByUserId(c, loginId); + } + } + + // -------------------- MAPPER -------------------- + private UserParamEntry mapRow(ResultSet rs) throws SQLException { return new UserParamEntry( rs.getLong("loginId"), diff --git a/shine-server-db/src/main/java/shine/db/dao/справка по DAO. Правило перегруженных методов.txt b/shine-server-db/src/main/java/shine/db/dao/справка по DAO. Правило перегруженных методов.txt new file mode 100644 index 0000000..b372f10 --- /dev/null +++ b/shine-server-db/src/main/java/shine/db/dao/справка по DAO. Правило перегруженных методов.txt @@ -0,0 +1,27 @@ +DAO: правило перегруженных методов (короткая справка) + +1) Всегда два метода: + +insert(Connection c, …) // не закрывает соединение, не коммитит +insert(…) // открывает своё соединение и сам закрывает + + +2) Внутри одного бизнес-метода: +открываем одно соединение conn = db.getConnection(); +делаем несколько DAO-вызовов через версии с Connection +в конце вручную conn.commit(); +conn закрываем только один раз в finally + +3) DAO-методы с Connection: +не создают соединение +не закрывают соединение +не делают commit/rollback + +4) DAO-методы без Connection: +маленькие удобные обёртки +открывают соединение в try-with-resources +внутри вызывают версию с Connection + +5) Итог: +одиночные операции → вызываем короткий метод без Connection +пакетные/атомарные операции → берём одно соединение и используем только методы с Connection \ No newline at end of file