Upsert monsterbook cards instead of delete -> insert

Also use existing connection during character saving for proper rollback.
This commit is contained in:
P0nk
2022-01-19 17:55:23 +01:00
parent 507ab06721
commit d6192385dd
4 changed files with 27 additions and 58 deletions

View File

@@ -8464,7 +8464,7 @@ public class Character extends AbstractCharacterObject {
ps.setInt(i + 31, getSlots(i));
}
monsterbook.saveCards(getId());
monsterbook.saveCards(con, id);
ps.setInt(36, bookCover);
ps.setInt(37, vanquisherStage);

View File

@@ -32,12 +32,9 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
public final class MonsterBook {
private static final Semaphore semaphore = new Semaphore(10);
private int specialCard = 0;
private int normalCard = 0;
private int bookLevel = 1;
@@ -180,61 +177,27 @@ public final class MonsterBook {
calculateLevel();
}
private static int saveStringConcat(char[] data, int pos, Integer i) {
return saveStringConcat(data, pos, i.toString());
}
public void saveCards(Connection con, int chrId) throws SQLException {
final String query = """
INSERT INTO monsterbook (charid, cardid, level)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE level = ?;
""";
try (final PreparedStatement ps = con.prepareStatement(query)) {
for (Map.Entry<Integer, Integer> cardAndLevel : cards.entrySet()) {
final int card = cardAndLevel.getKey();
final int level = cardAndLevel.getValue();
// insert
ps.setInt(1, chrId);
ps.setInt(2, card);
ps.setInt(3, level);
private static int saveStringConcat(char[] data, int pos, String s) {
int len = s.length();
for (int j = 0; j < len; j++) {
data[pos + j] = s.charAt(j);
}
// update
ps.setInt(4, level);
return pos + len;
}
private static String getSaveString(Integer charid, Set<Entry<Integer, Integer>> cardSet) {
semaphore.acquireUninterruptibly();
try {
char[] save = new char[400000]; // 500 * 10 * 10 * 8
int i = 0;
i = saveStringConcat(save, i, "INSERT INTO monsterbook VALUES ");
for (Entry<Integer, Integer> all : cardSet) { // assuming maxsize 500 unique cards
i = saveStringConcat(save, i, "(");
i = saveStringConcat(save, i, charid); //10 chars
i = saveStringConcat(save, i, ", ");
i = saveStringConcat(save, i, all.getKey()); //10 chars
i = saveStringConcat(save, i, ", ");
i = saveStringConcat(save, i, all.getValue()); //1 char due to being 0 ~ 5
i = saveStringConcat(save, i, "),");
ps.addBatch();
}
return new String(save, 0, i - 1);
} finally {
semaphore.release();
}
}
public void saveCards(final int charid) {
Set<Entry<Integer, Integer>> cardSet = getCardSet();
if (cardSet.isEmpty()) {
return;
}
try (Connection con = DatabaseConnection.getConnection()) {
try (PreparedStatement ps = con.prepareStatement("DELETE FROM monsterbook WHERE charid = ?")) {
ps.setInt(1, charid);
ps.executeUpdate();
}
try (PreparedStatement ps = con.prepareStatement(getSaveString(charid, cardSet))) {
ps.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
ps.executeBatch();
}
}