From 2bb8a321ffa368a455f81047e72d3f7f4e39fe2a Mon Sep 17 00:00:00 2001 From: windy664 <2580855214@qq.com> Date: Sun, 19 Jul 2026 22:31:14 +0800 Subject: [PATCH] fix: database compatibility and plugin-not-found graceful degradation Database compatibility improvements: - Replace ALTER TABLE IF NOT EXISTS with JDBC metadata checks for H2 compatibility - Add addColumnIfNotExists() and dropColumnIfExists() helper methods - Change address column from TEXT to VARCHAR(255) for UNIQUE constraint compatibility - Add null check for database connection in setup() - Throw RuntimeException on database setup failure instead of silent e.printStackTrace() Plugin-not-found graceful degradation: - UserConverter.readUser catches IllegalStateException from PluginUser.toUser - Base.getMails/getMail handle null sender/receiver with DummyMailUser fallback - Base.getMailTemplate(s) handle null sender with DummyMailUser fallback This prevents crashes when: - Using H2 database (default) instead of MySQL - Plugins that registered PluginMailUser are disabled/uninstalled - Database schema needs migration --- .../mailBox/database/UserConverter.java | 7 +- .../sabafly/mailBox/database/impl/Base.java | 76 +++++++++++++------ 2 files changed, 60 insertions(+), 23 deletions(-) diff --git a/paper/src/main/java/net/sabafly/mailBox/database/UserConverter.java b/paper/src/main/java/net/sabafly/mailBox/database/UserConverter.java index 6eb96bb..238bea3 100644 --- a/paper/src/main/java/net/sabafly/mailBox/database/UserConverter.java +++ b/paper/src/main/java/net/sabafly/mailBox/database/UserConverter.java @@ -30,7 +30,12 @@ public class UserConverter { if (baseUser == null) { return null; } - return baseUser.toUser(uuid, key); + try { + return baseUser.toUser(uuid, key); + } catch (IllegalStateException e) { + // 插件不存在时返回null + return null; + } } public static byte @NotNull [] toJson(@NotNull User user) { diff --git a/paper/src/main/java/net/sabafly/mailBox/database/impl/Base.java b/paper/src/main/java/net/sabafly/mailBox/database/impl/Base.java index 9dd8607..fee6aa0 100644 --- a/paper/src/main/java/net/sabafly/mailBox/database/impl/Base.java +++ b/paper/src/main/java/net/sabafly/mailBox/database/impl/Base.java @@ -38,7 +38,7 @@ public abstract class Base implements Database { CREATE TABLE IF NOT EXISTS mailbox_users ( uuid VARCHAR(36) PRIMARY KEY, user_data LONGBLOB DEFAULT NULL, - address TEXT DEFAULT NULL UNIQUE + address VARCHAR(255) DEFAULT NULL UNIQUE ) """; @@ -122,6 +122,9 @@ public void setup() { runner = new QueryRunner(); try (Connection conn = getConnection()) { + if (conn == null) { + throw new SQLException("Failed to get database connection"); + } runner.execute(conn, CREATE_TABLE_USERS); runner.execute(conn, CREATE_TABLE_MAILS); runner.execute(conn, CREATE_TABLE_MAIL_ATTACHMENTS); @@ -131,6 +134,7 @@ public void setup() { runner.execute(conn, CREATE_TABLE_USER_NOTIFICATION); } catch (SQLException e) { e.printStackTrace(); + throw new RuntimeException("Failed to setup database tables", e); } reload(); } @@ -140,32 +144,22 @@ public void setup() { public void reload() { try (Connection conn = getConnection()) { var fallbackPreview = ItemStack.of(Material.STONE).serializeAsBytes(); - runner.execute(conn, """ - ALTER TABLE mailbox_mail_attachments ADD COLUMN IF NOT EXISTS preview_item LONGBLOB DEFAULT NULL - """); - runner.execute(conn, """ - ALTER TABLE mailbox_mail_attachments DROP COLUMN IF EXISTS item_type - """); + + // 检查列是否存在,不存在则添加 + addColumnIfNotExists(conn, "mailbox_mail_attachments", "preview_item", "LONGBLOB DEFAULT NULL"); + dropColumnIfExists(conn, "mailbox_mail_attachments", "item_type"); runner.execute(conn, """ UPDATE mailbox_mail_attachments SET preview_item = ? WHERE preview_item IS NULL """, fallbackPreview); - runner.execute(conn, """ - ALTER TABLE mailbox_template_attachments ADD COLUMN IF NOT EXISTS preview_item LONGBLOB DEFAULT NULL - """); - runner.execute(conn, """ - ALTER TABLE mailbox_template_attachments DROP COLUMN IF EXISTS item_type - """); + + addColumnIfNotExists(conn, "mailbox_template_attachments", "preview_item", "LONGBLOB DEFAULT NULL"); + dropColumnIfExists(conn, "mailbox_template_attachments", "item_type"); runner.execute(conn, """ UPDATE mailbox_template_attachments SET preview_item = ? WHERE preview_item IS NULL """, fallbackPreview); - runner.execute(conn, """ - ALTER TABLE mailbox_users ADD COLUMN IF NOT EXISTS user_data LONGBLOB DEFAULT NULL - """); - - runner.execute(conn, """ - ALTER TABLE mailbox_users ADD COLUMN IF NOT EXISTS address TEXT DEFAULT NULL UNIQUE - """); + addColumnIfNotExists(conn, "mailbox_users", "user_data", "LONGBLOB DEFAULT NULL"); + addColumnIfNotExists(conn, "mailbox_users", "address", "VARCHAR(255) DEFAULT NULL UNIQUE"); getOrCreateUser(DummyMailUser.SYSTEM_USER); } catch (SQLException e) { @@ -173,6 +167,32 @@ public void reload() { } } + private void addColumnIfNotExists(Connection conn, String table, String column, String definition) throws SQLException { + try { + // 检查列是否存在(H2 默认大写存储标识符) + var rs = conn.getMetaData().getColumns(null, null, table.toUpperCase(), column.toUpperCase()); + if (!rs.next()) { + runner.execute(conn, "ALTER TABLE " + table + " ADD COLUMN " + column + " " + definition); + } + rs.close(); + } catch (SQLException e) { + // 如果表不存在或其他错误,忽略 + e.printStackTrace(); + } + } + + private void dropColumnIfExists(Connection conn, String table, String column) { + try { + var rs = conn.getMetaData().getColumns(null, null, table.toUpperCase(), column.toUpperCase()); + if (rs.next()) { + runner.execute(conn, "ALTER TABLE " + table + " DROP COLUMN " + column); + } + rs.close(); + } catch (SQLException e) { + // 忽略错误 + } + } + @Override public boolean isUserExists(@NotNull UUID uuid) { try (Connection conn = getConnection()) { @@ -329,7 +349,13 @@ INSERT INTO mailbox_users (uuid, user_data, address) VALUES (?, ?, ?) String content = rs.getString("content"); boolean isRead = rs.getBoolean("is_read"); LocalDateTime sentTime = rs.getTimestamp("sentTime").toLocalDateTime(); - Mail mail = new Mail(id, Objects.requireNonNull(sender), Objects.requireNonNull(receiver), title, content, List.of(), isRead, sentTime); + if (sender == null) { + sender = DummyMailUser.createUser(senderId, "Unknown Sender", "unknown", null); + } + if (receiver == null) { + receiver = DummyMailUser.createUser(receiverId, "Unknown Receiver", "unknown", null); + } + Mail mail = new Mail(id, sender, receiver, title, content, List.of(), isRead, sentTime); mail.attachments(getMailAttachments(mail)); mails.add(mail); } @@ -350,7 +376,13 @@ INSERT INTO mailbox_users (uuid, user_data, address) VALUES (?, ?, ?) String content = rs.getString("content"); boolean isRead = rs.getBoolean("is_read"); LocalDateTime sentTime = rs.getTimestamp("sentTime").toLocalDateTime(); - Mail mail = new Mail(id, Objects.requireNonNull(sender), Objects.requireNonNull(receiver), title, content, List.of(), isRead, sentTime); + if (sender == null) { + sender = DummyMailUser.createUser(senderId, "Unknown Sender", "unknown", null); + } + if (receiver == null) { + receiver = DummyMailUser.createUser(receiverId, "Unknown Receiver", "unknown", null); + } + Mail mail = new Mail(id, sender, receiver, title, content, List.of(), isRead, sentTime); mail.attachments(getMailAttachments(mail)); mails.add(mail); }