storing Hashmap content with custom class values into SQL Lite database

Discussion in 'Plugin Development' started by Father Of Time, Oct 8, 2011.

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

    Father Of Time

    Good afternoon all,

    Well a plugin I am working on is coming along great. I have a lot of the main functionality I wanted working minus a few features that I will work on later. However, one of the most important features of this plugin is not currently working and I don't know how to go about starting it.

    At this point I have a main plugin class that stores player names as keys and a custom riftbook class as the value:

    Code:
        public static Map<Player, RiftBook> RiftCraftDB = new HashMap<Player, RiftBook>();
    
    And the riftbook class looks as follows:

    Code:
    package me.FatherTime.RiftCraft;
    
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.bukkit.Location;
    import org.bukkit.entity.Player;
    
    class RiftBook
    {
        public Map<String, Location> Inscriptions = new HashMap<String, Location>();
        public Date LastUsed;
    
        public RiftBook()
        {
        }
    
        public void MarkLocation( Player player, Location loc, String name )
        {
            Inscriptions.put(name, loc);
        }
    
        public void RiftToLocation( Player player, String inscription )
        {
            Location destination = GetLocation( inscription );
            player.teleport(destination);
        }
    
        public Location GetLocation( String name )
        {
            return Inscriptions.get( name );
        }
    
        public boolean HasInscription( String name )
        {
            return Inscriptions.containsKey(name.toLowerCase());
        }
    
        public void RemoveInscription( String inscription )
        {
            Inscriptions.remove(inscription);
        }
    }
    
    Every time a player uses this command if they do note already have a riftbook associated to them it generates a Riftbook and places it in the dictionary with the players name as as the key and the newly generated Riftbook as the value. As you can see inside the riftbook is another hashmap, with a string as the key and a Location as the value ( import org.bukkit.Location; ).

    So with this information you know the general information I am looking to save to a SQL Lite database. I have absolutely no idea where to look or how to begin handling this. I have been trying trail and error, and searching for guilds on this but I have had little success in finding anything but an SQL library found here.

    If anyone can help me accomplish the generation of a new SQL lite database in the plugin configuration direction, and then populate the database with the information from the RiftCraftDB Hashtable I would be infinately appriciative. Of coarse if anyone decide to help me I can provide them with the full source code, and show them a live demonstration of this plugin thus far.

    Thank you to all who take the time to read this thread.
     
  2. Offline

    wwsean08

    well as far as the columns go for the database i would think you would want player name, riftname, world, x, y, z, that should be all you need in saving it I think. The reason that I broke down the location is because you can't really save the location nicely, however with those 4 values you can use the constructor to recreate it. I'm not a database person, however that is likely the most basic setup you can have
     
    Father Of Time likes this.
  3. Offline

    Father Of Time

    First and foremost thank you for taking the time to reply. I should be able to figure out the table structures of the SQL database itself, but I am more perplexed on how to get bukkit to generate the SQL Lite database in the plugin directory, how to get the plugin to connect to that database, and how to read and write to the database.

    Anything regarding the above processes would be extremely appricated. Is the SQL library built into Bukkit usable, or do I need to install that SQL library that I found on the "how to connect to a database" tutorial on the bukkit plugin development tutorial page?

    Thank you again for taking time to assist me with this issue!
     
  4. Offline

    wwsean08

    i don't think there is a built in one, but there is a sql library here, I haven't used it (as I haven't needed a database for any of my projects), but it looks very good
     
  5. Offline

    Celeixen

    I think sql was added to the most recent builds. There is a few tutorials in resouces that you could probably usr.
     
  6. Offline

    ZerothAngel

    Bukkit comes with Avaje Ebeans and exposes a simple interface that plugins can use (e.g. the getDatabaseClasses(), getDatabase(), and installDDL() methods in the JavaPlugin class).

    I'm not sure if a Bukkit tutorial for it exists. And a familiarity with JPA helps a lot. But I think it hasn't really caught on due to these reasons.

    Anyway, its use makes things really easy for the server administrator: it is database-agnostic (to a degree... SQLite seems to choke on more complex data models where other databases do fine) and it has a one-stop configuration in bukkit.yml which applies to all plugins using it.
     
  7. Offline

    Father Of Time

    Hmm, I wish I would have seen your post before hand, but sadly I have push forward using the library listed above. However the good news is I have made amazing progress this far and have it creating the SQLite database, creating the table structure, and the serialization/deserialization methods.

    However, even though everything is performing correctly (by that I mean not throwing any SQL or Java errors) the data isn't recovering after world save (its not automatic yet, but I have temporary /save and /load commands).

    So really I have two main questions:
    1) what is a good tool to navigate the table structure of a SQLite database so I can confirm the data is writing properly
    2) what would be the best way to automate this? I only need to load when the server starts, so I'm assuming I should do my serialization in the OnEnable method. The saving however I'm still deciding on. I would like to find an event that is triggered by the server saving and have it export from the HashMap records to the database on each world save, but before that I would like to know what the natural save interval of Minecraft SMP is.

    I can't really move forward without the above information, so anyone with some ability to shed some light on these issues would be greatly appriciated. Thank you to all who take the time to review this post.

    EDIT: Well I found the answer to my first question, I found an SQLite database manager add-on for firefox which seems to be working.
     
  8. Suggestion: DO NOT store Player objects. Store a String of the player.getName() and then use Bukkit.getPlayer(string);
    This is to prevent NPE's when the player logs out
     
  9. Offline

    Father Of Time

    I see, should be simple enough to fix, although that stinks because I have used player a lot. Out of curiousity what is NPE's, No Player Error?

    Also, Im a bit perplexed. At this point I have the server generating a database and populating it with the proper Data Type structure, however when ever I attempt to run a query to insert records the server freezes when it hits the query. The query works when I do a manual record insert into SQLite manager, but crashes the server when the server attempts to write a record. Does anyone see anything wrong with my syntax or anything for that matter?

    Code:
    INSERT INTO RiftBookLocations (RecordID, Playe
    rName, LocationName, World, XCoord, YCoord, ZCoord) VALUES(NULL, 'vermillion2083
    ', 'ser', 'Serenity', -611.28125, 88.0, 4861.03125)
    which is being inserted using the following code:

    Code:
                            String InsertQuery = "INSERT INTO RiftBookLocations (RecordID, PlayerName, LocationName, World, XCoord, YCoord, ZCoord) VALUES(NULL, '" + playername + "', '" + locname + "', '" + world + "', " + xcoord + ", " + ycoord + ", " + zcoord + ")";
                            RiftCraft.log.info("Made it to query: " + InsertQuery);
                            RiftCraft.RiftCraftSQLDB.query(InsertQuery);
                            RiftCraft.log.info("Passed query.");
    
    And I do have checks to make sure that I am connecting to both the database and table correctly. I am not getting any errors, simply the server makes it up to

    Code:
    RiftCraft.log.info("Made it to query: " + InsertQuery);
    
    And then locks up, eventually freezing the server. Does anyone have any suggestions as to why this is happening?
     
  10. NullPointerException. Means a object is null. Its not hard to fix ;)
     
  11. Offline

    Father Of Time

    I'm sorry but I am going to need further explination. I don't see why any of my values are null, I do a print of the query right before it actually processes it and every value is populated with information I expect.

    Am I misunderstanding you?

    EDIT: the first value being passes is to an auto imcrement recordID field, from what I've read I should pass that variable as NULL in SQLite, am I mistaken?

    EDIT2: I just remove the RecordID variable and NULL value from the insert statement, but the server still freezes just the same.
     
  12. Offline

    Celeixen

    Wait you can store player objects now? What about block because i always hate splitting up the x,y,z . I thought they werent serializable :/
     
  13. Offline

    Father Of Time

    Store player objects in what sense? if you mean as a bukkit variable to pass around multiple variables as one player object then yes:

    Code:
    import org.bukkit.entity.Player;
    But if you mean can you store the player object in a SQLite database as a data type, no this is not possible.

    Forgive me if I have misunderstood your question. :eek:

    Some additional information. I realized that I don't need to have my saving working properly to test my loading, so I decided to go into my database manager and manually insert a few records, then I went into game and triggered the load function and sure enough it worked perfectly!

    This means that I am creating a database and table properly, and connecting to both to retrieve data. So the issue purely seems to be with the query execution. This is the only part that I believe is holding up database management, does anyone have any ideas?

    Okay I apologize about the multiple post, but I keep making progress before any has a chance to respond. I found this information about SQLite databases:
    http://www.sqlite.org/lang_insert.html

    it states that the proper insert syntax for SQLite is:

    INSERT INTO DATABASENAME.TABLENAME....etc....

    I was just doing:

    INSERT INTO TABLENAME....etc.....

    So ever since I inserted this the system is no longer locking up and continuing past the problem code. However even though the server is freezing now it is putting off the following message in the log and not recording the data.

    I have tried every database name I can think of; I tried the actual filename, I tried the local variable name, but none of them seem to fix this error. Does anyone have any suggestions on how to fix this?
    Thanks for the help guys, It's so close to being fixed!

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 20, 2016
  14. Offline

    Celeixen

    Damn, i meant storing it as a datatype. Guess i am going to need to use strings for the name.
     
Thread Status:
Not open for further replies.

Share This Page