@@ -29,50 +29,55 @@ public class DataIO {
2929 // ===== 1. SAVE ============================================
3030 // ===========================================================
3131
32- /** グループ全体を保存(各テーブルへの分割保存) */
33- public static boolean saveGroupData (GroupData g ) {
34- try (Connection conn = db .getConnection ()) {
35- // group_table
36- saveGroupTable (conn , g );
37- saveGroupMembers (conn , g );
32+ /** グループ全体を保存(各テーブルへの分割保存) */
33+ public static boolean saveGroupData (GroupData g ) {
34+ try (Connection conn = db .getConnection ()) {
35+ // group_table
36+ saveGroupTable (conn , g );
37+ saveGroupMembers (conn , g );
3838
39- if (g .storageData != null ) {
40- saveStorageData (conn , g );
39+ if (g .storageData != null ) {
40+ saveStorageData (conn , g );
4141
42- for (Map .Entry <String , InventoryData > entry : g .storageData .storageInventory .entrySet ()) {
43- String pageId = entry .getKey ();
44- InventoryData inv = entry .getValue ();
42+ for (Map .Entry <String , InventoryData > entry : g .storageData .storageInventory .entrySet ()) {
43+ String pageId = entry .getKey ();
44+ InventoryData inv = entry .getValue ();
4545
46- if (!inv .isFullyLoaded ()) {
47- Bukkit .getLogger ().info ("[BetterStorage] スキップ: " + g .groupName + "/" + pageId + " は未完全のため保存されません" );
48- continue ;
49- }
46+ if (!inv .isFullyLoaded ()) {
47+ Bukkit .getLogger ().info ("[BetterStorage] スキップ: " + g .groupName + "/" + pageId + " は未完全のため保存されません" );
48+ continue ;
49+ }
5050
51- if (!saveSinglePage (conn , g , pageId , inv )) {
52- return false ; // ここで失敗通知
51+ if (!saveSinglePage (conn , g , pageId , inv )) {
52+ return false ; // ここで失敗通知
53+ }
5354 }
5455 }
55- }
5656
57- // 差分ログを保存
58- UnifiedLogManager .saveDiffLogs (BetterStorage .BSPlugin .getDatabaseManager (), g );
59- return true ;
57+ // 差分ログを保存
58+ UnifiedLogManager .saveDiffLogs (BetterStorage .BSPlugin .getDatabaseManager (), g );
59+ return true ;
6060
61- } catch (SQLException e ) {
62- Bukkit .getLogger ().warning ("GroupDataの保存に失敗: " + e .getMessage ());
63- return false ;
61+ } catch (SQLException e ) {
62+ Bukkit .getLogger ().warning ("GroupDataの保存に失敗: " + e .getMessage ());
63+ return false ;
64+ }
6465 }
65- }
6666
6767 private static boolean saveSinglePage (Connection conn , GroupData g , String pageId , InventoryData inv ) throws SQLException {
6868 // 🔁 versionチェック
6969 long dbPageVersion = getInventoryPageVersion (conn , g .groupUUID , g .ownerPlugin , pageId );
70- Bukkit .getLogger ().info ("[Debug] pageId=" + pageId + ", client=" + inv .version + ", db=" + dbPageVersion );
71- if (dbPageVersion != 0 && dbPageVersion != inv .version ) {
70+ Bukkit .getLogger ().info ("[Debug]保存前最終チェック pageId=" + pageId + ", client=" + inv .version + ", db=" + dbPageVersion );
71+
72+ if (dbPageVersion != inv .version ) {
7273 Bukkit .getLogger ().warning ("[BetterStorage] ページバージョン不一致: " + pageId );
7374 return false ;
7475 }
7576
77+ // ✅ 楽観ロック:保存前に version を進める
78+ inv .version ++;
79+
80+ Bukkit .getLogger ().info ("[Debug]この内容で保存します pageId=" + pageId + ", client=" + inv .version + ", db=" + dbPageVersion );
7681
7782 // ---------- inventory_table ----------
7883 String invSql = "REPLACE INTO inventory_table " +
@@ -85,13 +90,11 @@ private static boolean saveSinglePage(Connection conn, GroupData g, String pageI
8590 ps .setString (4 , inv .displayName );
8691 ps .setInt (5 , inv .rows );
8792 ps .setString (6 , gson .toJson (inv .requirePermission ));
88- ps .setLong (7 , inv .version );
93+ ps .setLong (7 , inv .version ); // 新しいバージョンで保存
8994 ps .executeUpdate ();
9095 }
9196
92-
9397 // ---------- inventory_item_table ----------
94- // 🔥 1. 既存スロットとitemstack取得
9598 Map <Integer , String > oldSlotBase64Map = new HashMap <>();
9699 String fetchSql = "SELECT slot, itemstack FROM inventory_item_table WHERE group_uuid = ? AND page_id = ?" ;
97100 try (PreparedStatement ps = conn .prepareStatement (fetchSql )) {
@@ -106,7 +109,7 @@ private static boolean saveSinglePage(Connection conn, GroupData g, String pageI
106109
107110 Set <Integer > currentSlots = inv .itemStackSlot .keySet ();
108111
109- // 🔥 2. 削除されたスロットを DELETE & ログ記録
112+ // 削除されたスロット
110113 Set <Integer > slotsToDelete = new HashSet <>(oldSlotBase64Map .keySet ());
111114 slotsToDelete .removeAll (currentSlots );
112115 if (!slotsToDelete .isEmpty ()) {
@@ -131,7 +134,7 @@ private static boolean saveSinglePage(Connection conn, GroupData g, String pageI
131134 }
132135 }
133136
134- // 🔥 3. 追加・更新されたスロットを REPLACE & ログ記録
137+ // 追加・更新スロット
135138 String itemSql = "REPLACE INTO inventory_item_table (group_uuid, plugin_name, page_id, slot, itemstack, display_name, display_name_plain, material, amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" ;
136139 try (PreparedStatement ps = conn .prepareStatement (itemSql )) {
137140 for (Map .Entry <Integer , ItemStack > itemEntry : inv .itemStackSlot .entrySet ()) {
@@ -169,7 +172,6 @@ private static boolean saveSinglePage(Connection conn, GroupData g, String pageI
169172 ps .executeBatch ();
170173 }
171174
172-
173175 // ---------- tag_table ----------
174176 String tagSql = "REPLACE INTO tag_table (group_uuid, plugin_name, page_id, user_tag) VALUES (?, ?, ?, ?)" ;
175177 try (PreparedStatement ps = conn .prepareStatement (tagSql )) {
@@ -185,110 +187,110 @@ private static boolean saveSinglePage(Connection conn, GroupData g, String pageI
185187 }
186188 }
187189
188- inv .version = dbPageVersion + 1 ;
189190 return true ;
190191 }
191192
192193
193194
195+
194196 // ---------- SAVE / group ----------
195- private static void saveGroupTable (Connection conn , GroupData g ) throws SQLException {
196- String sql = "REPLACE INTO group_table (group_uuid, group_name, display_name, is_private, owner_plugin) VALUES (?, ?, ?, ?, ?)" ;
197- try (PreparedStatement ps = conn .prepareStatement (sql )) {
198- ps .setString (1 , g .groupUUID .toString ());
199- ps .setString (2 , g .groupName );
200- ps .setString (3 , g .displayName );
201- ps .setBoolean (4 , g .isPrivate );
202- ps .setString (5 , g .ownerPlugin );
203- ps .executeUpdate ();
197+ private static void saveGroupTable (Connection conn , GroupData g ) throws SQLException {
198+ String sql = "REPLACE INTO group_table (group_uuid, group_name, display_name, is_private, owner_plugin) VALUES (?, ?, ?, ?, ?)" ;
199+ try (PreparedStatement ps = conn .prepareStatement (sql )) {
200+ ps .setString (1 , g .groupUUID .toString ());
201+ ps .setString (2 , g .groupName );
202+ ps .setString (3 , g .displayName );
203+ ps .setBoolean (4 , g .isPrivate );
204+ ps .setString (5 , g .ownerPlugin );
205+ ps .executeUpdate ();
206+ }
204207 }
205- }
206208
207- private static void saveGroupMembers (Connection conn , GroupData g ) throws SQLException {
208- String sql = "REPLACE INTO group_member_table (group_uuid, member_uuid, role) VALUES (?, ?, ?)" ;
209- try (PreparedStatement ps = conn .prepareStatement (sql )) {
210- for (OfflinePlayer member : g .playerList ) {
211- String [] roles = g .playerPermission .get (member );
212- if (roles != null ) {
213- for (String role : roles ) {
214- ps .setString (1 , g .groupUUID .toString ());
215- ps .setString (2 , member .getUniqueId ().toString ());
216- ps .setString (3 , role );
217- ps .addBatch ();
209+ private static void saveGroupMembers (Connection conn , GroupData g ) throws SQLException {
210+ String sql = "REPLACE INTO group_member_table (group_uuid, member_uuid, role) VALUES (?, ?, ?)" ;
211+ try (PreparedStatement ps = conn .prepareStatement (sql )) {
212+ for (OfflinePlayer member : g .playerList ) {
213+ String [] roles = g .playerPermission .get (member );
214+ if (roles != null ) {
215+ for (String role : roles ) {
216+ ps .setString (1 , g .groupUUID .toString ());
217+ ps .setString (2 , member .getUniqueId ().toString ());
218+ ps .setString (3 , role );
219+ ps .addBatch ();
220+ }
218221 }
219222 }
223+ ps .executeBatch ();
220224 }
221- ps .executeBatch ();
222225 }
223- }
224226
225- // ---------- SAVE / storage ----------
226- private static void saveStorageData (Connection conn , GroupData g ) throws SQLException {
227- StorageData s = g .storageData ;
228- String sql = "REPLACE INTO storage_table (group_uuid, plugin_name, bank_money, require_bank_permission) VALUES (?, ?, ?, ?)" ;
229- try (PreparedStatement ps = conn .prepareStatement (sql )) {
230- ps .setString (1 , g .groupUUID .toString ());
231- ps .setString (2 , g .ownerPlugin );
232- ps .setDouble (3 , s .bankMoney );
233- ps .setString (4 , gson .toJson (s .requireBankPermission ));
234- ps .executeUpdate ();
227+ // ---------- SAVE / storage ----------
228+ private static void saveStorageData (Connection conn , GroupData g ) throws SQLException {
229+ StorageData s = g .storageData ;
230+ String sql = "REPLACE INTO storage_table (group_uuid, plugin_name, bank_money, require_bank_permission) VALUES (?, ?, ?, ?)" ;
231+ try (PreparedStatement ps = conn .prepareStatement (sql )) {
232+ ps .setString (1 , g .groupUUID .toString ());
233+ ps .setString (2 , g .ownerPlugin );
234+ ps .setDouble (3 , s .bankMoney );
235+ ps .setString (4 , gson .toJson (s .requireBankPermission ));
236+ ps .executeUpdate ();
237+ }
235238 }
236- }
237239
238- public static boolean saveInventoryOnly (GroupData g , StorageData storageData , String pageId ) {
239- try (Connection conn = db .getConnection ()) {
240- InventoryData inv = storageData .storageInventory .get (pageId );
241- storageData .groupUUID = g .groupUUID ;
242- g .storageData = storageData ;
243- if (inv == null ) {
244- Bukkit .getLogger ().warning ("インベントリが空のままセーブしようとしたため失敗しました" );
245- return false ;
246- }
240+ public static boolean saveInventoryOnly (GroupData g , StorageData storageData , String pageId ) {
241+ try (Connection conn = db .getConnection ()) {
242+ InventoryData inv = storageData .storageInventory .get (pageId );
243+ storageData .groupUUID = g .groupUUID ;
244+ g .storageData = storageData ;
245+ if (inv == null ) {
246+ Bukkit .getLogger ().warning ("インベントリが空のままセーブしようとしたため失敗しました" );
247+ return false ;
248+ }
247249
248- if (!inv .isFullyLoaded ()) {
249- Bukkit .getLogger ().warning ("ロードされていないデータをセーブしようとしました" );
250- g .storageData .loadPage (conn , g .ownerPlugin , pageId );
251- inv = g .storageData .storageInventory .get (pageId );
252- }
250+ if (!inv .isFullyLoaded ()) {
251+ Bukkit .getLogger ().warning ("ロードされていないデータをセーブしようとしました" );
252+ g .storageData .loadPage (conn , g .ownerPlugin , pageId );
253+ inv = g .storageData .storageInventory .get (pageId );
254+ }
253255
254- long dbPageVersion = getInventoryPageVersion (conn , g .groupUUID , g .ownerPlugin , pageId );
255- if (dbPageVersion != inv .version ) {
256- Bukkit .getLogger ().warning ("[BetterStorage]Error:InventoryDataVersion不一致:" + g .groupName );
257- Bukkit .getLogger ().warning ("[BetterStorage]DB上のVer:" + dbPageVersion + "保存しようとしたVer:" + inv .version );
258- return false ;
259- }
256+ long dbPageVersion = getInventoryPageVersion (conn , g .groupUUID , g .ownerPlugin , pageId );
257+ if (dbPageVersion != inv .version ) {
258+ Bukkit .getLogger ().warning ("[BetterStorage]Error:InventoryDataVersion不一致:" + g .groupName );
259+ Bukkit .getLogger ().warning ("[BetterStorage]DB上のVer:" + dbPageVersion + "保存しようとしたVer:" + inv .version );
260+ return false ;
261+ }
260262
261- saveSinglePage (conn , g , pageId , inv );
262- saveGroupTable (conn , g ); // group_tableは必須(versionが無くても更新してOK)
263+ saveSinglePage (conn , g , pageId , inv );
264+ saveGroupTable (conn , g ); // group_tableは必須(versionが無くても更新してOK)
263265
264- UnifiedLogManager .saveDiffLogs (BetterStorage .BSPlugin .getDatabaseManager (), g );
265- return true ;
266- } catch (SQLException e ) {
267- Bukkit .getLogger ().warning ("Inventory保存失敗: " + e .getMessage ());
268- return false ;
266+ UnifiedLogManager .saveDiffLogs (BetterStorage .BSPlugin .getDatabaseManager (), g );
267+ return true ;
268+ } catch (SQLException e ) {
269+ Bukkit .getLogger ().warning ("Inventory保存失敗: " + e .getMessage ());
270+ return false ;
271+ }
269272 }
270- }
271273
272- private static void saveTags (Connection conn , GroupData g ) throws SQLException {
273- String sql = "REPLACE INTO tag_table (group_uuid, plugin_name, page_id, user_tag) VALUES (?, ?, ?, ?)" ;
274- try (PreparedStatement ps = conn .prepareStatement (sql )) {
275- for (Map .Entry <String , InventoryData > entry : g .storageData .storageInventory .entrySet ()) {
276- String pageId = entry .getKey ();
277- List <String > tags = entry .getValue ().userTags ;
278-
279- if (tags != null && !tags .isEmpty ()) {
280- for (String tag : tags ) {
281- ps .setString (1 , g .groupUUID .toString ());
282- ps .setString (2 , g .ownerPlugin );
283- ps .setString (3 , pageId );
284- ps .setString (4 , tag );
285- ps .addBatch ();
274+ private static void saveTags (Connection conn , GroupData g ) throws SQLException {
275+ String sql = "REPLACE INTO tag_table (group_uuid, plugin_name, page_id, user_tag) VALUES (?, ?, ?, ?)" ;
276+ try (PreparedStatement ps = conn .prepareStatement (sql )) {
277+ for (Map .Entry <String , InventoryData > entry : g .storageData .storageInventory .entrySet ()) {
278+ String pageId = entry .getKey ();
279+ List <String > tags = entry .getValue ().userTags ;
280+
281+ if (tags != null && !tags .isEmpty ()) {
282+ for (String tag : tags ) {
283+ ps .setString (1 , g .groupUUID .toString ());
284+ ps .setString (2 , g .ownerPlugin );
285+ ps .setString (3 , pageId );
286+ ps .setString (4 , tag );
287+ ps .addBatch ();
288+ }
286289 }
287290 }
291+ ps .executeBatch ();
288292 }
289- ps .executeBatch ();
290293 }
291- }
292294 // ===========================================================
293295 // ===== 2. LOAD ============================================
294296 // ===========================================================
0 commit comments