1. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Помогите Java & SQLite

Тема в разделе "Разработка плагинов для новичков", создана пользователем Korvinius, 9 май 2016.

  1. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    Эм, я дико извиняюсь, но, подскажите еще, что еще нужно прописать в "onEnable", чтобы можно было с этим работать :oops:?
     
  2. ql_Nik_lp

    ql_Nik_lp Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    q-nik-p
    Имя в Minecraft:
    ql_Nik_lp
    Если я правильно понял - вызвать load()
     
  3. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    вероятно я его не правильно вызывал, так как этот способ:
    Код:
        private SQLite sqlite;
    
        @Override
        public void onEnable() {   
    
            sqlite.load();
    приводит к ошибке:

    Код:
    [17:27:40 ERROR]: Error occurred while enabling Mystery v0.4/1 (Is it up to date?)
    java.lang.NullPointerException
            at net.wealth_mc.mystery.Mystery.onEnable(Mystery.java:106) ~[?:?]
            at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:292) ~[server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:340) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:405) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.bukkit.craftbukkit.v1_9_R1.CraftServer.loadPlugin(CraftServer.java:361) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.bukkit.craftbukkit.v1_9_R1.CraftServer.enablePlugins(CraftServer.java:321) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.MinecraftServer.t(MinecraftServer.java:411) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.MinecraftServer.l(MinecraftServer.java:376) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.MinecraftServer.a(MinecraftServer.java:331) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.DedicatedServer.init(DedicatedServer.java:269) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.MinecraftServer.run(MinecraftServer.java:527) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_77]
    И 106-я строка, именно эта: sqlite.load();
     
  4. Dereku

    Dereku Старожил Пользователь

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Ты пишешь "sqlite.load(); ", а в jvm оно выглядит как "null.load();".
     
  5. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    а, блин, точно, забыл добавить sqlite = new SQLite(this); спасибо, с этим прошло, родило новые ошибки, походу что то я напартачил в самом SQL запросе, попробую сначала сам разобраться...
     
  6. Dereku

    Dereku Старожил Пользователь

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    лайк.
     
  7. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    Спасибо. С ошибкой я разобрался.
    Но, к сожалению с толкнулся с новой, решение к которой пока не могу найти. Суть в том, что когда база уже создана, но в ней еще нет записей, есть метод, который проверяет БД на наличие в ней определенной записи перед добавлением/обновлением. В результате получаю такую ошибку:
    Код:
    java.sql.SQLException: ResultSet closed
            at org.sqlite.RS.checkOpen(RS.java:63) ~[server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.sqlite.RS.markCol(RS.java:77) ~[server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.sqlite.RS.wasNull(RS.java:208) ~[server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.wealth_mc.mystery.db.MysterySQLite.getThisMysteryPlayerToNameDB(MysterySQLite.java:39) [Mystery.jar:?]
            at net.wealth_mc.mystery.Mystery.getConfigPlayerPrefix(Mystery.java:172) [Mystery.jar:?]
            at net.wealth_mc.mystery.Mystery.loadConfMystery(Mystery.java:128) [Mystery.jar:?]
            at net.wealth_mc.mystery.Mystery.onEnable(Mystery.java:83) [Mystery.jar:?]
            at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:292) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:340) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:405) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.bukkit.craftbukkit.v1_9_R1.CraftServer.loadPlugin(CraftServer.java:361) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at org.bukkit.craftbukkit.v1_9_R1.CraftServer.enablePlugins(CraftServer.java:321) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.MinecraftServer.t(MinecraftServer.java:411) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.MinecraftServer.l(MinecraftServer.java:376) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.MinecraftServer.a(MinecraftServer.java:331) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.DedicatedServer.init(DedicatedServer.java:269) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at net.minecraft.server.v1_9_R1.MinecraftServer.run(MinecraftServer.java:527) [server11486.jar:git-Spigot-944aa20-8d16fc0]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_77]
    вот этот кусок кода:
    Код:
        public MysteryPlayer getThisMysteryPlayerToNameDB(String playername) {
            MysteryPlayer pl = null;
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            conn = getSQLConnection();
            try {
                ps = conn.prepareStatement("SELECT * FROM " + mystery_player_list
                        + " WHERE displayName = '" + playername.toLowerCase() + "';");
                rs = ps.executeQuery();
    
    /*MysterySQLite.java:39*/pl = new MysteryPlayer(UUID.fromString(rs.getString("uniqueId")), rs.getString("displayName"),
                        Gender.valueOf(rs.getString("gender")), Legacy.valueOf(rs.getString("legacy")),
                        rs.getInt("level"), rs.getInt("timeLevel"), rs.getInt("killLevel"),
                        rs.getInt("killTheirLegacy"), rs.getInt("killAlienLegacy"), rs.getInt("killNotLegacy"));
    
            } catch (SQLException ex) {
                plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionExecute(), ex);
            } finally {
                try {
                    if (ps != null)
                        ps.close();
                    if (conn != null)
                        conn.close();
                } catch (SQLException ex) {
                    plugin.getLogger().log(Level.SEVERE, Errors.sqlConnectionClose(), ex);
                }
            }
            return pl;
        }
    я знаю, что ошибка из-за того, что запрос не может выполниться, так как в базе нет совпадений этому запросу, по сути в базе еще совсем нет записей, но как прервать метод, если строка не найдена?
    Пробовал : if (rs == null) return pl; не помогает, вероятно переменная не совсем пустая, а такие варианты:
    if (rs.wasNull()) return pl; или if (rs.first()) return pl; приводят к аналогичной ошибке на них-же, подскажите, как можно прервать выполнение этого метода, если искомая запись не найдена?
     
  8. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Код:
    at net.wealth_mc.mystery.db.MysterySQLite.getThisMysteryPlayerToNameDB
       (MysterySQLite.java:39)
    Это которая строка у тебя в коде выше? Тьфу, я слепой.
    Твоя переменная rs является не той самой единственной строкой результата, которую ты ждёшь, а кортежем строк (коих может быть в количестве от 0 до N).
    Нужно использовать rs.next(), и если оно даёт true, значит в rs загружена следующая непрочитанная строка. Вот, например, как я извлекаю все полученные строки. Правда, это MySQL, а не SQLite.

    Гуру БД при желании могут поправить меня, ибо я далеко не pro.
     
  9. Larin

    Larin Старожил Пользователь

    Баллы:
    103
    Ребят, читайте больше книг =)
    Это же JDBC! Видов реляционных БД много, а стандарт один.(Для noSQL не подойдёт!)
     
  10. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    Спасибо большое, это решило мою проблему! Сделал так:
    Код:
                while(rs.next()){
                    if (rs.getString("displayName").equalsIgnoreCase(playername.toLowerCase())) {
                        pl = new MysteryPlayer(UUID.fromString(rs.getString("uniqueId")), rs.getString("displayName"),
                                Gender.valueOf(rs.getString("gender")), Legacy.valueOf(rs.getString("legacy")),
                                rs.getInt("level"), rs.getInt("timeLevel"), rs.getInt("killLevel"),
                                rs.getInt("killTheirLegacy"), rs.getInt("killAlienLegacy"),
                                rs.getInt("killNotLegacy"));
                    }
                }

    Еще хотел посоветоваться.

    1. Как практичнее, работать напрямую с БД или считывать с базы инфу в массив и там уже обрабатывать?

    2. Если работать напрямую с базой, то в отдельные потоки выводить абсолютно всю работу с ней или короткие запросы можно делать в основном, а запись и более сложные в дополнительном?

    3. Если все делать в дополнительных потоках, то частые запросы к БД (хоть и не сложные, просто получение инфы), то есть будет создаваться много потоков (конечно в зависимости от онлайна) не создадут ли они большой нагрузки на сервер?
     
  11. Dereku

    Dereku Старожил Пользователь

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Иногда уходит больше времени на создание потока, чем на его выполнение.

    Вообще лучше (имхо) вытащить всю инфу из бд в память и работать уже с памятью. И где то раз в 10 минут кидать в бд изменения.
     
  12. Dereku

    Dereku Старожил Пользователь

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    По доброму нужно.
     
  13. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Вызовы в БД — медленные. Если она удалённая, то особенно.
    Всё, что работает медленно, обязано работать в параллельном потоке. Единственное исключение — можно быстренько что-то запросить при загрузке сервера в onLoad или onEnable (менее желательно).
    Всё, что можно не вычислять, а хранить готовым локально — съест память, но ускорит работу.
    Таковы основные принципы.
     
  14. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    это как?
     
  15. hobabibs

    hobabibs Новичок Пользователь

    Баллы:
    16
    Имя в Minecraft:
    bhtyujnbfyu8
    Создаешь пул (гугли как), после чего задачу, которую нужно выполнить асинхронно, выполняешь в пуле потоков, таким образом берется уже созданный поток, который стоит на паузе, в нем выполняется задача и он снова становится доступен для другой задачи.
     
  16. Dereku

    Dereku Старожил Пользователь

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    3 ms ещё не медленно.
     
  17. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Если придерживаться мысли, что медленно, хуже не будет =)
     
  18. Dereku

    Dereku Старожил Пользователь

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Просто есть ещё более медленные операции. * Кивает в сторону SQLite *
     
  19. Автор темы
    Korvinius

    Korvinius Активный участник Пользователь

    Баллы:
    88
    так ведь SQLite, это локальная БД, чисто теоретически, должна бы работать быстрее, или на практике нет?
    а, еще в дополнение, если у меня кое какие задачи выполняются по таймеру, ну то есть "шедулеры", они выполняются в каком потоке? (сори за нубские вопросы:oops:)
     
  20. Dereku

    Dereku Старожил Пользователь

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Это бд в файле, который нужно периодически сохранять/загружать. Некоторые драйверы из-за таймаута просто выгружают бд из памяти, из-за чего нужно бд снова прочитать и загрузить. Возможно, это неверное суждение, поскольку оно у меня работало более менее шустро (от 0 до 16 ms).
     

Поделиться этой страницей