Solved Few SQLite Database problems

Discussion in 'Plugin Development' started by Chlorek, Dec 7, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    Chlorek

    Hi, I've got following problem. I've got SQLite database with some columns and primary key set as 'player'. Queries works fine (I can create table), but I can't set any value in database and I can load only one value (weird, isn't it?). By saying "only one value" I mean when I call query to get first value it works, but every next returns always 0 (zero).

    I've got the following code:
    Code:java
    1. public static long getPlayerLongValueFromDatabase(String player, String key)
    2. {
    3. long res = getLongResult(Database.getInstance().query("SELECT `player`,`" + key + "` FROM `stats` WHERE `player`='" + player + "'"), 2);
    4. if(res == 0)
    5. {
    6. if(!key.equals("strength") && !key.equals("dexterity") && !key.equals("mana") && !key.equals("exp") && !key.equals("level") && !key.equals("learnpoints") && !key.equals("health"))
    7. {
    8. gothicCraft.getLogger().severe("Requested invalid player value type \""+ key +"\" <DatabaseHelper::getPlayerLongValueFromDatabase()>");
    9. return res;
    10. }
    11.  
    12. setPlayerLongValueInDatabase(player, key, res);
    13. }
    14.  
    15. return res;
    16. }


    Code:java
    1. public static void setPlayerLongValueInDatabase(String player, String key, long value)
    2. {
    3. Database.getInstance().query("INSERT OR IGNORE INTO `stats`(`player`,`" + key + "`) VALUES('" + player + "', '" + value + "')");
    4. Database.getInstance().query("UPDATE `stats` SET `" + key + "`='" + value + "' WHERE `player`='" + value + "'");
    5. }


    I get no errors. I used these queries in few projects and it always worked. The only thing that changed this time is that I added caching data, so now I call saving to database this way:
    Code:java
    1. public static void savePlayerDataToDatabase(String player)
    2. {
    3. PlayerData tmp = null;
    4. for(int i = 0; i < cachedData.size(); i++)
    5. {
    6. tmp = cachedData.get(i);
    7. if(tmp.getPlayerName().equals(player))
    8. {
    9. DatabaseHelper.setPlayerLongValueInDatabase(player, "strength", tmp.getStrength());
    10. DatabaseHelper.setPlayerLongValueInDatabase(player, "dexterity", tmp.getDexterity());
    11. DatabaseHelper.setPlayerLongValueInDatabase(player, "mana", tmp.getMana());
    12. DatabaseHelper.setPlayerLongValueInDatabase(player, "exp", tmp.getExperience());
    13. DatabaseHelper.setPlayerLongValueInDatabase(player, "level", tmp.getLevel());
    14. DatabaseHelper.setPlayerLongValueInDatabase(player, "health", tmp.getHealth());
    15. DatabaseHelper.setPlayerLongValueInDatabase(player, "learnpoints", tmp.getLearnPoints());
    16. DatabaseHelper.setPlayerStringValueInDatabase(player, "extraskills", tmp.getExtraSkills());
    17.  
    18. return;
    19. }
    20. }
    21.  
    22. gothicCraft.getLogger().severe("Could not save data for player \""+ player + "\"!");
    23. }


    I made check and I am sure that data is cached correctly. All values are in cache, they just are not saved in database.

    Thanks for your effort in reading this. I hope you can help.

    Anyone? Please, it's really important :oops: And I can't figure out what is the problem. I spent today over 6 hours trying to fix that!

    Come on, please. Need help with that!

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 5, 2016
  2. Offline

    Njol

    I recommend to change your save queries to a single one, and to use a PreparedStatement:

    Code:java
    1. // put this where you connect to the database
    2. //replace "..." with all fields, and make sure to use the correct amount of '?'s, or alternatively use the "`field`=?" syntax
    3. PreparedStatement s = Database.getInstance().prepare("REPLACE INTO `stats` (`player`, `strength`, `dexterity`, ...) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");

    Code:java
    1. // and use this in savePlayerDataToDatabase():
    2. int i = 1;
    3. s.setString(i++, player);
    4. s.setLong(i++, tmp.getStrength(),);
    5. s.setLong(i++, tmp.getDexterity(),);
    6. // etc.
    7.  
    8. s.execute();


    edit: This is how I read values from my database, using a PreparedStatement and a ResultSet:
    Code:java
    1. monitorQuery = ((Database) db).prepare("SELECT name, type, value, rowid FROM " + TABLE_NAME + " WHERE rowid > ? AND update_guid != ?");
    2.  
    3. // ...
    4.  
    5. monitorQuery.setLong(1, lastRowID);
    6. monitorQuery.setString(2, guid);
    7. monitorQuery.execute();
    8. ResultSet r = null;
    9. try {
    10. r = monitorQuery.getResultSet();
    11. loadVariables(r);
    12. } finally {
    13. if (r != null)
    14. r.close();
    15. }
    16.  
    17. // ...
    18.  
    19. private void loadVariables(final ResultSet r) throws SQLException {
    20. synchronized (syncDeserializing) {
    21. while (r.next()) { // iterates over all returned rows
    22. int i = 1;
    23. final String name = r.getString(i++);
    24. final String type = r.getString(i++);
    25. final Blob value = r.getBlob(i++);
    26. // etc.
     
    Chlorek likes this.
  3. Offline

    Chlorek

    Njol
    Thank You very much. Also I was thinking about PreparedStatement's. Thanks for nice code. I hope it will fix my problem. I'll check it and tell if it works.

    #Edit
    I've got problem with prepare() method. What should I call it for? I mean what is the class? I use my custom one Database Class and I have not the following method there.
     
  4. Offline

    Njol

    You likely need to use "connection.prepareStatement(query)". prepare() is a method of SQLibrary which I use in my plugin.
     
    Chlorek likes this.
  5. Offline

    Chlorek

    Njol
    Help me, still does not work. I don't understand it, why? Value reading works, not just saving (reading is still query, not a prepared statement).

    Why the hell on the earth I can't set value in database and other queries work fine. Well I can set value but ONCE. Every next setting value does not work ;/

    I just found that when using PreparedStatement I get error that tells SQL statement does not return ResultSet. How is it connected with my problem?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 5, 2016
  6. Offline

    maciekmm

    You must use .executeQuery() , it returns ResultSet

    Code:java
    1.  
    2. PreparedStatement stmt = yourConnection.prepareStatement("UPDATE `stats` SET ?=? WHERE `player`=?");
    3. stmt.setString(1,key);
    4. stmt.setString(2,value);
    5. stmt.setString(3,player);
    6. stmt.executeUpdate();}
    Something like this?
     
    Chlorek likes this.
  7. Offline

    Chlorek

    Code:
    14:51:29 [SEVERE] java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (near "?": syntax error)
    maciekmm
    That's what I get.
     
  8. Offline

    maciekmm

    put System.out.println(stmt.toString()); after executeUpdate and paste it here.
     
  9. Offline

    Chlorek

    maciekmm
    It throws exception on prepareStatement() method. I can't get it to string then...

    YEAAAAAAAAAAAAAAAAAAAAAAAAA!!!
    It works, I changed statement to:
    Code:
    "UPDATE `stats` SET `"+key+"`=? WHERE `player`=?"
    And changed setString() etc. to match new format.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 5, 2016
Thread Status:
Not open for further replies.

Share This Page