129 lines
4.2 KiB
Java
129 lines
4.2 KiB
Java
package shine.db.dao;
|
|
|
|
import shine.db.SqliteDbController;
|
|
import shine.db.entities.SolanaUserEntry;
|
|
|
|
import java.sql.*;
|
|
|
|
/**
|
|
* UserCreateDAO — атомарное добавление пользователя:
|
|
* - solana_users (login, blockchain_name, solana_key, blockchain_key, device_key)
|
|
* - blockchain_state (blockchain_name, login, blockchain_key, size_limit, ... last_block_number=-1 ...)
|
|
*
|
|
* ВАЖНО:
|
|
* - только INSERT (без перезаписи существующих записей)
|
|
* - если login или blockchainName заняты — возвращаем false (пользователь уже есть/занято)
|
|
*/
|
|
public final class UserCreateDAO {
|
|
|
|
private static volatile UserCreateDAO instance;
|
|
private final SqliteDbController db = SqliteDbController.getInstance();
|
|
private final SolanaUsersDAO usersDao = SolanaUsersDAO.getInstance();
|
|
|
|
private UserCreateDAO() {}
|
|
|
|
public static UserCreateDAO getInstance() {
|
|
if (instance == null) {
|
|
synchronized (UserCreateDAO.class) {
|
|
if (instance == null) instance = new UserCreateDAO();
|
|
}
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* @return true если добавили; false если занято (login уже есть или blockchainName уже существует).
|
|
*/
|
|
public boolean insertUserWithBlockchain(
|
|
String login,
|
|
String blockchainName,
|
|
String solanaKey,
|
|
String blockchainKey,
|
|
String deviceKey,
|
|
long sizeLimit,
|
|
long nowMs
|
|
) throws SQLException {
|
|
|
|
try (Connection c = db.getConnection()) {
|
|
boolean oldAuto = c.getAutoCommit();
|
|
c.setAutoCommit(false);
|
|
|
|
try {
|
|
// 1) solana_users
|
|
SolanaUserEntry u = new SolanaUserEntry();
|
|
u.setLogin(login);
|
|
u.setBlockchainName(blockchainName);
|
|
u.setSolanaKey(solanaKey);
|
|
u.setBlockchainKey(blockchainKey);
|
|
u.setDeviceKey(deviceKey);
|
|
|
|
usersDao.insert(c, u); // если login занят (NOCASE) или blockchainName (unique) -> constraint
|
|
|
|
// 2) blockchain_state — строго INSERT, без UPSERT (иначе можно перезаписать существующую цепочку)
|
|
insertBlockchainStateStrict(
|
|
c,
|
|
blockchainName,
|
|
login,
|
|
blockchainKey,
|
|
sizeLimit,
|
|
nowMs
|
|
);
|
|
|
|
c.commit();
|
|
return true;
|
|
|
|
} catch (SQLException e) {
|
|
c.rollback();
|
|
|
|
String msg = e.getMessage() == null ? "" : e.getMessage().toLowerCase();
|
|
if (msg.contains("constraint")) {
|
|
return false;
|
|
}
|
|
throw e;
|
|
|
|
} finally {
|
|
c.setAutoCommit(oldAuto);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void insertBlockchainStateStrict(
|
|
Connection c,
|
|
String blockchainName,
|
|
String login,
|
|
String blockchainKey,
|
|
long sizeLimit,
|
|
long nowMs
|
|
) throws SQLException {
|
|
|
|
String sql = """
|
|
INSERT INTO blockchain_state (
|
|
blockchain_name,
|
|
login,
|
|
blockchain_key,
|
|
size_limit,
|
|
file_size_bytes,
|
|
last_block_number,
|
|
last_block_hash,
|
|
updated_at_ms
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
""";
|
|
|
|
try (PreparedStatement ps = c.prepareStatement(sql)) {
|
|
int i = 1;
|
|
ps.setString(i++, blockchainName);
|
|
ps.setString(i++, login);
|
|
ps.setString(i++, blockchainKey);
|
|
|
|
ps.setLong(i++, sizeLimit);
|
|
ps.setLong(i++, 0L);
|
|
|
|
ps.setInt(i++, -1);
|
|
ps.setNull(i++, Types.BLOB); // старт: блоков ещё нет
|
|
ps.setLong(i++, nowMs);
|
|
|
|
ps.executeUpdate(); // если blockchainName занят -> constraint (PK)
|
|
}
|
|
}
|
|
}
|