结果集自动关闭

Nam*_*iel 0 java bots discord

我的 Discord 音乐机器人有问题。我想在曲目开始时发送嵌入消息,但 ResultSet 始终关闭。所以它不能通过 if-query。

这是我的代码(类“TrackScheduler”):

try {
                
                file = new URL("https://img.youtube.com/vi/" + videoID + "/hqdefault.jpg").openStream();
                builder.setImage("attachment://thumbnail.png");
                
                System.out.println("4");
                
                ResultSet set = LiteSQL.onQuery("SELECT * FROM musicchannel WHERE guildid = " + guildid);
                
                try {
                    System.out.println("3");
                    
                    if(set.next()) {
                        long channelid = set.getLong("channelid");
                                                
                        TextChannel channel;
                        
                        System.out.println("2");
                        
                        if((channel = guild.getTextChannelById(channelid)) != null) {
                            
                            System.out.println("1");
                            
                            channel.sendTyping().queue();
                            channel.sendFile(file, "thumbnail.png").embed(builder.build()).queue();
                        }                   
                    }

                }
                catch (SQLException e) {
                    e.printStackTrace();
                }
                
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
Run Code Online (Sandbox Code Playgroud)

我的 LiteSQL.onQuery(类“LiteSQL”):

private static Connection c;
    
    private static Statement s;

public static ResultSet onQuery(String sql) {
        
        try {
            
            return s.executeQuery(sql);
        }
        catch(SQLException e) {
            e.printStackTrace();
        }
        
        return null;
    }
Run Code Online (Sandbox Code Playgroud)

这是错误:

ava.sql.SQLException: ResultSet closed
        at org.sqlite.core.CoreResultSet.checkOpen(CoreResultSet.java:76)
        at org.sqlite.jdbc3.JDBC3ResultSet.findColumn(JDBC3ResultSet.java:39)
        at org.sqlite.jdbc3.JDBC3ResultSet.getLong(JDBC3ResultSet.java:423)
        at de.nameddaniel.bot.musik.TrackScheduler.onTrackStart(TrackScheduler.java:79)
        at com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter.onEvent(AudioEventAdapter.java:72)
        at com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayer.dispatchEvent(DefaultAudioPlayer.java:368)
        at com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayer.startTrack(DefaultAudioPlayer.java:117)
        at com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayer.playTrack(DefaultAudioPlayer.java:80)
        at de.nameddaniel.bot.musik.AudioLoadResult.trackLoaded(AudioLoadResult.java:20)
        at com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager.checkSourcesForItemOnce(DefaultAudioPlayerManager.java:443)
        at com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager.checkSourcesForItem(DefaultAudioPlayerManager.java:419)
        at com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager.lambda$createItemLoader$0(DefaultAudioPlayerManager.java:218)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

我是新来的,所以如果有任何遗漏的信息,请告诉我。同样,我很抱歉格式不正确。

你好,丹尼尔:)

rzw*_*oot 5

tl;博士

不要static在您的StatementConnection字段上使用。

细节

  1. 此代码存在安全漏洞。查找 SQL 注入。基本要点是:语句几乎完全没用。您想要PreparedStatement,并且您希望您的 SQL 查询仅是字符串文字。永远不要通过连接用户输入来“制作查询字符串”。比方说,查询字符串应该是SELECT * FROM musicchannel WHERE guildid = ?(是的,字符串中带有文字问号),然后使用 的setInt方法PreparedStatement来设置公会 ID。或者更好的是,由于 JDBC API 并不是真正为这样的消费而设计的,因此请使用JDBI 之类的东西

  2. 这是糟糕的异常处理。如果您不知道该怎么做,那么正确的“我不知道”catch 块是throw new RuntimeException("Uncaught", e);而不是e.printStackTrace();。更好的是,让这些方法只抛出 SQLException;显然做数据库事情的方法应该抛出那个。请注意,您的 main 方法可以(并且应该)声明为抛出异常。

  3. Connection、PreparedStatement 和 ResultSets 都是资源,需要通过try-with-resources打开。不这样做意味着您的应用程序存在泄漏,并且如果运行时间足够长就会破坏某些内容。对于 DB 代码,DB 最终将耗尽连接并变得完全无法访问,直到您关闭 Java 应用程序。这就是为什么你需要尝试资源。

  4. 您只有一个 Statement 和 Connection(这些字段是静态的)。大概你的 discord bot 可以收到不止一条消息,所以如果你尝试发送不止一条消息,系统就会着火。不要在这里使用“静态”。您粘贴的代码本身不包含任何会关闭 ResultSet 的内容,但是通过从静态重新设计,问题可能会自行消失。

  • 你说的一切都是真的,但#4是OP问题的实际答案。 (2认同)