本帖最后由 夜雨晨风丶 于 2023-3-12 17:53 编辑
复制代码
插件第一次加载数据库时会执行这个方法建立连接建表
复制代码但是加载到ConfigFile.loadConfig()时就产生报错了
复制代码复制代码
报错如下
复制代码
是我哪里写错了吗,表确实在插件加载时创建好了,但是在创建好之后进行的第一次加载表数据不知道是哪出了问题。如果代码提供的不够详细可以直接查看源码 github
- @Override
- public void onEnable() {
- Instance = this;
- //检测是否存在插件文件夹,如果没有则进行创建
- File dataFolder = getDataFolder();
- if (!dataFolder.exists()) {
- dataFolder.mkdirs();
- }
- //检查存储模式,如果是YAML则创建items.yml文件,如果是MySQL则跳过创建文件
- if (getConfig().getString("saveMode").equalsIgnoreCase("yaml")) {
- createItemsFile();
- } else {
- // 实例化SqlStorage并传入插件实例
- SqlStorage sql = new SqlStorage(this);
- sql.saveDespawnItemsToMySQL();
- }
- //保存默认配置并加载数据
- saveDefaultConfig();
- ConfigFile.loadConfig();
插件第一次加载数据库时会执行这个方法建立连接建表
- public void saveDespawnItemsToMySQL() {
- Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
- Connection conn = null;
- PreparedStatement pstmt = null;
- try {
- //连接到MySQL数据库
- Class.forName("com.mysql.jdbc.Driver");
- conn = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?useSSL=false", username, password);
- //创建表
- pstmt = conn.prepareStatement("CREATE TABLE IF NOT EXISTS despawn_items (id INT NOT NULL AUTO_INCREMENT, item_data BLOB, PRIMARY KEY (id))");
- pstmt.executeUpdate();
- //插入每个ItemStack
- for (ItemStack itemStack : ConfigFile.despawnItems) {
- pstmt = conn.prepareStatement("INSERT INTO despawn_items (item_data) VALUES (?)");
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream);
- dataOutput.writeObject(itemStack);
- dataOutput.flush();
- dataOutput.close();
- pstmt.setBytes(1, outputStream.toByteArray());
- pstmt.executeUpdate();
- }
- } catch (SQLException | ClassNotFoundException | IOException e) {
- e.printStackTrace();
- } finally {
- //关闭连接
- try {
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- });
- }
- public static void loadConfig() {
- ItemsProtect ip = ItemsProtect.getInstance();
- ip.reloadConfig();
- ...
- if (saveMode.equalsIgnoreCase("yaml")) {
- loadDespawnItems(ip);
- } else {
- sql.loadDespawnItemsFromMySQL(items -> {
- // 处理物品列表
- ConfigFile.despawnItems = items;
- });
- }
- }
- public void loadDespawnItemsFromMySQL(Consumer<List<ItemStack>> callback) {
- Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
- List<ItemStack> itemList = new ArrayList<>();
- Connection conn = null;
- PreparedStatement pstmt = null;
- ResultSet rs = null;
- try {
- //连接到MySQL数据库
- Class.forName("com.mysql.jdbc.Driver");
- conn = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?useSSL=false", username, password);
- //从表中检索每个ItemStack
- pstmt = conn.prepareStatement("SELECT item_data FROM despawn_items");
- rs = pstmt.executeQuery();
- while (rs.next()) {
- byte[] bytes = rs.getBytes("item_data");
- ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
- BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream);
- ItemStack itemStack = (ItemStack) dataInput.readObject();
- itemList.add(itemStack);
- }
- //将检索到的ItemStacks赋值给ConfigFile中的despawnItems
- ConfigFile.despawnItems = itemList;
- //执行回调函数
- callback.accept(itemList);
- } catch (SQLException | IOException | ClassNotFoundException e) {
- e.printStackTrace();
- } finally {
- //关闭连接和资源
- try {
- if (rs != null) rs.close();
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- });
- }
报错如下
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'noinvput.despawn_items' doesn't exist
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.Util.getInstance(Util.java:408)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:944)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2484)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1966)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at cordori.itemsprotect.utils.SqlStorage.lambda$loadDespawnItemsFromMySQL$1(SqlStorage.java:84)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftTask.run(CraftTask.java:64)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:52)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
- [05:01:10] [Craft Scheduler Thread - 6/WARN]: at java.lang.Thread.run(Thread.java:750)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'noinvput.despawn_items' doesn't exist
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.Util.getInstance(Util.java:408)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:944)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2484)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1966)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at cordori.itemsprotect.utils.SqlStorage.lambda$loadDespawnItemsFromMySQL$1(SqlStorage.java:84)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftTask.run(CraftTask.java:64)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:52)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
- [05:01:10] [Craft Scheduler Thread - 7/WARN]: at java.lang.Thread.run(Thread.java:750)
是我哪里写错了吗,表确实在插件加载时创建好了,但是在创建好之后进行的第一次加载表数据不知道是哪出了问题。如果代码提供的不够详细可以直接查看源码 github
本帖最后由 名副其实 于 2023-3-12 08:55 编辑
所请求的表在数据库文件中不存在。
检查一下你的代码是不是没创建这个名叫 noinvput.despawn_items 的表。
呃呃,很有可能是链接数据库或者创建表的时候没到位,你检查一下你那两个 sql 命令是不是写错了
所请求的表在数据库文件中不存在。
检查一下你的代码是不是没创建这个名叫 noinvput.despawn_items 的表。
呃呃,很有可能是链接数据库或者创建表的时候没到位,你检查一下你那两个 sql 命令是不是写错了
异步出了问题
你在
ConfigFile.loadConfig(); 前调用了 sql.saveDespawnItemsToMySQL(); 按顺序来说应该是先创建的,但异步调度器执行任务不提供顺序承诺,并无法保证 ConfigFile.loadConfig() 一定是在数据表创建后执行,因为SQL操作需要网络IO,很多时候都会耗时更长。
bukkit本身生命周期设计,插件Enable逻辑执行时调度器并没有开始调度,也就是说saveDespawnItemsToMySQL 的逻辑实际是在插件 enable 逻辑之后才会执行,查看表在创建表前执行了,必然会报错找不到表
也就是说你理解的执行顺序是
---
enable语句块:
1. 创建表
2. 调用表
---
但实际是
---
enable语句块:
1. 提交创建表任务
2. 调用表
3. 执行创建表任务
---
可以通过在saveDespawnItemsToMySQL中加入一句log输出语句来验证这一点
所以在服务器启动时会报错,但完全启动后数据表存在
解决方法也很多,将读取表作为异步任务的回调,通过一个标识位,或是设计任务队列来保证表的调用一定在创建逻辑之后执行等
你在
ConfigFile.loadConfig(); 前调用了 sql.saveDespawnItemsToMySQL(); 按顺序来说应该是先创建的,但异步调度器执行任务不提供顺序承诺,并无法保证 ConfigFile.loadConfig() 一定是在数据表创建后执行,因为SQL操作需要网络IO,很多时候都会耗时更长。
bukkit本身生命周期设计,插件Enable逻辑执行时调度器并没有开始调度,也就是说saveDespawnItemsToMySQL 的逻辑实际是在插件 enable 逻辑之后才会执行,查看表在创建表前执行了,必然会报错找不到表
也就是说你理解的执行顺序是
---
enable语句块:
1. 创建表
2. 调用表
---
但实际是
---
enable语句块:
1. 提交创建表任务
2. 调用表
3. 执行创建表任务
---
可以通过在saveDespawnItemsToMySQL中加入一句log输出语句来验证这一点
所以在服务器启动时会报错,但完全启动后数据表存在
解决方法也很多,将读取表作为异步任务的回调,通过一个标识位,或是设计任务队列来保证表的调用一定在创建逻辑之后执行等