I'm using Ormlite, for my android app, to store my data. I want to download a database from a site and after this, the program checks if a database exists. If a database exists, then the new database and the old database should merge.
Here comes my problem. In Ormlite you create a Dao to interact with the tables of a database and I wanted to know, how I can interact with the new database after the download?
For example:
Database A from the app has the items:
Cheese, Eggs, Milk, Chicken
Database B from the download has the items:
Cheese, Eggs, Milk, Flour, Bread
At the end I want:
Cheese, Eggs, Milk, Flour, Bread, Chicken and only one database left.
And to clarify: Yes, it exists questions "How to merge databases".
For example:
Android update - merge database contents?
But that is not my problem. I want to know, how to interact with the new database with Ormlite. Which way exists, that I can get access to the new database?
Edit:
I tried to download the database and guarantee that the version is always higher than the old database version. Therefore, at least that what I thought, it would go in OnUpgrade method and there I could merge the database. But i just replaced the old database.
I also tried to make a second OrmDBHelper with another name, so after the download I could use the methods there. But no errors or anything whatsoever.
Here is the database helper from the existing database and the second one is the same, except the name.
public class OrmDbHelper extends OrmLiteSqliteOpenHelper {
public static final String LOG = OrmDbHelper.class.getName();
public static final String DB_NAME = "bestand.db";
public static final int DB_VERSION = 1;
public OrmDbHelper(Context context) {
super(context, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()
+ File.separator + DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
try {
TableUtils.createTableIfNotExists(connectionSource, ScanItem.class);
TableUtils.createTableIfNotExists(connectionSource, BestandItem.class);
TableUtils.createTableIfNotExists(connectionSource, SettingsItem.class);
} catch (SQLException ex) {
Log.e(LOG, "Error Creating table", ex);
}
}
#Override
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
TableUtils.dropTable(connectionSource, ScanItem.class, true);
TableUtils.dropTable(connectionSource, BestandItem.class, true);
TableUtils.dropTable(connectionSource, SettingsItem.class, true);
TableUtils.createTable(connectionSource, ScanItem.class);
TableUtils.createTable(connectionSource, BestandItem.class);
TableUtils.createTable(connectionSource, SettingsItem.class);
} catch (SQLException ex) {
Log.e(LOG, "Error Updating table", ex);
}
}
public Dao<ScanItem, Integer> createScanItemDAO() {
try {
return DaoManager.createDao(connectionSource, ScanItem.class);
} catch (SQLException ex) {
Log.e(LOG, "Error Creating DAO for Todo class", ex);
}
return null;
}
public Dao<BestandItem, Integer> createBestandItemDAO() {
try {
return DaoManager.createDao(connectionSource, BestandItem.class);
} catch (SQLException ex) {
Log.e(LOG, "Error Creating DAO for Todo class", ex);
}
return null;
}
public Dao<SettingsItem, Integer> createSettingItemDAO() {
try {
return DaoManager.createDao(connectionSource, SettingsItem.class);
} catch (SQLException ex) {
Log.e(LOG, "Error Creating DAO for Todo class", ex);
}
return null;
}
}
And here is how I tried to get access to the second database:
The access to the first database works, but to the second one doesnt. I even checked if the download of the second database works, which it does.
public class OrmDataHelper {
private Dao<ScanItem, Integer> scanItemDAO;
private Dao<BestandItem, Integer> bestandItemDAO;
private Dao<SettingsItem, Integer> settingsItemsDAO;
public OrmDataHelper(Context context) {
OrmDbHelper ormDbHelper = new OrmDbHelper(context);
scanItemDAO = ormDbHelper.createScanItemDAO();
bestandItemDAO = ormDbHelper.createBestandItemDAO();
settingsItemsDAO = ormDbHelper.createSettingItemDAO();
}
public ArrayList<ScanItem> getAllScanItem() {
ArrayList<ScanItem> temp = null;
try {
temp = new ArrayList<>(scanItemDAO.queryForAll());
} catch (SQLException ex) {
ex.getMessage();
}
return temp;
}
Related
So i'm trying to run multiple PDF files through a function that scrapes the text, compares it to a static dictionary , then adds it's relational data to an index table in MYSQL. I looked into multi-threading but am not sure if this would achieve what I need.
Here is the for loop where I am going through all the PDF files
for(String temp: files){
//addToDict(temp,dictonary,conn);
//new Scraper(temp,dictonary,conn).run();
Scraper obj=new Scraper(temp,dictonary,conn);
Thread T1 =new Thread(obj);
T1.start();
//System.out.println((ammountOfFiles--)+" files left");
}
And here is the Scraper class I created that implements runnable
public class Scraper implements Runnable {
private String filePath;
private HashMap<String,Integer> map;
private Connection conn;
public Scraper(String file_path,HashMap<String,Integer> dict,Connection connection) {
// store parameter for later user
filePath =file_path;
map = dict;
conn = connection;
}
#Override
public void run() {
//cut file path so it starts from the data folder
int cutPos = filePath.indexOf("Data");
String cutPath = filePath.substring(cutPos);
cutPath = cutPath.replaceAll("\\\\", "|");
System.out.println(cutPath+" being scrapped");
// Queries
String addSentanceQuery ="INSERT INTO sentance(sentance_ID,sentance_Value) VALUES(Default,?)";
String addContextQuery ="INSERT INTO context(context_ID,word_ID,sentance_ID,pdf_path) VALUES(Default,?,?,?)";
// Prepared Statementes
// RESULT SETS
ResultSet sentanceKeyRS=null;
BodyContentHandler handler = new BodyContentHandler(-1);
Metadata metadata = new Metadata();
FileInputStream inputstream = null;
try {
inputstream = new FileInputStream(new File(filePath));
} catch (FileNotFoundException ex) {
Logger.getLogger(Scraper.class.getName()).log(Level.SEVERE, null, ex);
}
ParseContext pcontext = new ParseContext();
//parsing the document using PDF parser
PDFParser pdfparser = new PDFParser();
try {
pdfparser.parse(inputstream, handler, metadata, pcontext);
} catch (IOException ex) {
Logger.getLogger(Scraper.class.getName()).log(Level.SEVERE, null, ex);
} catch (SAXException ex) {
Logger.getLogger(Scraper.class.getName()).log(Level.SEVERE, null, ex);
} catch (TikaException ex) {
Logger.getLogger(Scraper.class.getName()).log(Level.SEVERE, null, ex);
}
//getting the content of the document
String fileText = handler.toString();
fileText = fileText.toLowerCase();
//spilt text by new line
String sentances [] = fileText.split("\\n");
for(String x : sentances){
x = x.trim();
if(x.isEmpty() || x.matches("\\t+") || x.matches("\\n+") || x.matches("")){
}else{
int sentanceID = 0;
//add sentance to db and get the id
try (PreparedStatement addSentancePrepare = conn.prepareStatement(addSentanceQuery,Statement.RETURN_GENERATED_KEYS)) {
addSentancePrepare.setString(1, x);
addSentancePrepare.executeUpdate();
sentanceKeyRS = addSentancePrepare.getGeneratedKeys();
while (sentanceKeyRS.next()) {
sentanceID = sentanceKeyRS.getInt(1);
}
addSentancePrepare.close();
sentanceKeyRS.close();
} catch (SQLException ex) {
Logger.getLogger(Scraper.class.getName()).log(Level.SEVERE, null, ex);
}
String words [] = x.split(" ");
for(String y : words){
y = y.trim();
if(y.matches("\\s+") || y.matches("")){
}else if(map.containsKey(y)){
//get ID and put in middle table
try (PreparedStatement addContextPrepare = conn.prepareStatement(addContextQuery)) {
addContextPrepare.setInt(1, map.get(y));
addContextPrepare.setInt(2, sentanceID);
addContextPrepare.setString(3, cutPath);
addContextPrepare.executeUpdate();
addContextPrepare.close();
} catch (SQLException ex) {
Logger.getLogger(Scraper.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
try {
inputstream.close();
} catch (IOException ex) {
Logger.getLogger(Scraper.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Am I going about this correctly? I have never used multi threading but it seems like it would speed up my program.
You completed the basic modeling of your program. Conceptually, you got it almost right. Few concerns though.
Scalability
you simply cannot increase the number of threads as you get more files to process. Even though increasing number of concurrent workers should increase the performance as we feel, in real world it might not be the case. When number of threads increases pass a certain level (depends on various parameters) actually the performance decreases.(due to thread contention, communication, memory usage). So I;m proposing you to use a ThreadPool implementation comes with java concurrent package. Refer to the following modification I did to your code.
public class Test {
private final ThreadPoolExecutor threadPoolExecutor;
public Test(int coreSize, int maxSize) {
this.threadPoolExecutor = new ThreadPoolExecutor(coreSize,maxSize, 50, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(100));
}
public void submit(String[] files) {
for(String temp: files){
//addToDict(temp,dictonary,conn);
//new Scraper(temp,dictonary,conn).run();
Scraper obj=new Scraper(temp,dictonary,conn);
threadPoolExecutor.submit(obj);
//System.out.println((ammountOfFiles--)+" files left");
}
}
public void shutDown() {
this.threadPoolExecutor.shutdown();
}
}
Thread safety and Synchronization
I can see you have shared the java.sql.Connection instance across the threads. Eventhough java.sql.Connection is thread safe, this usage will drop your app performance significantly since java.sql.Connection achives thread safety through synchronization. So only one thread would be able to use the connection at a time. To overcome this we can use a Connection Pooling concept. One simple impl i could suggest is Apache Commons dbcp
I had the following code, which is responsible for assigning roles and groups to users.
private void override(List<Assignment> assignments) {
removeAll();
addMultiple(assignments);
}
protected void removeAll() {
removeAllRoles();
removeAllGroups();
}
private void removeAllGroups() {
Iterator<String> userGroups = user.getParentGroups(false);
while (userGroups.hasNext()) {
UMHelper.removeUserFromGroup(user.getUniqueID(), userGroups.next());
}
}
private void addMultiple(List<Assignment> assignments) {
for (Assignment assignment : assignments) {
add(assignment);
}
}
public static void addUserToGroup(String userId, String groupId) {
try {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Trying to add user " + userId + " to group " + groupId);
groupFactory.addUserToGroup(userId, groupId);
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Success");
} catch (UMException e) {
SimpleLogger.traceThrowable(Severity.ERROR, loc, "Addition failed", e);
}
}
I hope the logic is pretty clear. Most of the code is iteration over collections. Adding a user to role or group can cause exception, which I report in log.
Since I find it not good to suppress exceptions and because a client calling override method should know the result of assigment, I rewrote the code adding exception handling. The execution should continue, even if some assignments failed.
private void override(List<Assignment> assignments) {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Override was started with " + assignments.size() + " assignments");
try {
removeAll();
} catch (UMException e) {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Removing all existing elements failed");
}
try {
addMultiple(assignments);
} catch (UMException e) {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Adding new elements failed");
}
}
protected void removeAll() throws UMException {
boolean successfulRemoval = true;
try {
removeAllRoles();
} catch (UMException e) {
successfulRemoval = false;
}
try {
removeAllGroups();
} catch (UMException e) {
successfulRemoval = false;
}
if (!successfulRemoval){
throw new UMException("Not all user elements could be removed");
}
}
private void removeAllGroups() throws UMException {
boolean removeSuccessful = true;
Iterator<String> userGroups = user.getParentGroups(false);
while (userGroups.hasNext()) {
try {
UMHelper.removeUserFromGroup(user.getUniqueID(), userGroups.next());
} catch (UMException e) {
removeSuccessful = false;
}
}
if (!removeSuccessful) {
throw new UMException("Not all user groups could be removed");
}
}
private void addMultiple(List<Assignment> assignments) throws UMException {
boolean additionSuccessful = true;
for (Assignment assignment : assignments) {
try {
add(assignment);
} catch (UMException e) {
additionSuccessful = false;
}
}
if (!additionSuccessful) {
throw new UMException("Addition of new rights failed");
}
}
public static void addUserToGroup(String userId, String groupId) throws UMException {
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Trying to add user " + userId + " to group " + groupId);
groupFactory.addUserToGroup(userId, groupId);
SimpleLogger.log(Severity.INFO, Category.APPLICATIONS, loc, null, "Success");
}
Now the code got 3 times bigger and not as clear as it was. If I just had to stop execution after first assignment failed, the code would have been easier, but that's the requirement. Do I handle exceptions wrong or is there a way to improve the code?
In this scenario I would change all these methods from throwing exceptions to
returning a boolean value which indicates if they did their job successfully or not.
If you have control over these methods and can do this change, I think that's better
suited for your scenario.
With a little code reorganization, that is, all removals/additions/etc are in a single transaction, the code can be made clearer, as in, for instance:
String failmsg = null;
// tx is some transaction object
tx.start();
try {
failmsg = "user removal failed";
tx.removeUsers();
failmsg = "group removal failed";
tx.removeGroups();
failmsg = "new additions failed";
tx.addNew();
tx.commit();
} catch (UMException e) {
tx.rollback();
log(failmsg);
} finally {
tx.close();
}
I want to create a database, and fill it at the start of application. It will remain same and will never change. There will be like 1000 entries. What is the good way to do this?
I created the table so far, but now i have to fill it with 1000 entries. Is there an UI for it?
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE "+TABLE_NAME+" ("+
UID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+
USER_NAME+" TEXT NOT NULL, "+
USER_TYPE+" TEXT NOT NULL, "+
USER_CLASS+" TEXT NOT NULL);"
);
Several ways to improve the performance:
As Tsunaze suggests, you should do this in another thread, you can check AsyncTask which is the "default" tool provided in the SDK to do this.
Consider using transactions:
db.beginTransaction();
for(...){
db.insert(...);
}
db.commit();
In this way you will only write to the database when you finish inserting all the values, speeding up the process.
Do massive inserts:
insert into table
select value1X, value1Y, value1Z
union all
select value2X, value2Y, value2Z
union all
select value3X, value3Y, value3Z
union all
select value4X, value4Y, value4Z
you can create file "table_inserts.sql" and put it in "raw" folder.
private void insertValues(SQLiteDatabase db) {
db.beginTransaction();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(R.raw.table_inserts))));
String s;
while ((s = reader.readLine()) != null) {
db.execSQL(s);
}
reader.close();
} catch (IOException ignored) {
}
db.setTransactionSuccessful();
db.endTransaction();
}
or your can write all inserts in code.
You need to do it in a thread, to no block the main UI:
public void addObjects(List<Object> objects, OnQueryListener listener){
listener.begin();
database.beginTransaction();
for(int i = 0; i < objects.size();i++{
// Add
}
database.setTransactionSuccessful();
database.endTransaction();
listener.end();
}
private interface OnQueryListener{
void begin();
void end();
}
And in your main Code do something like this :
Handler h = new Handler();
Thread t = new Thread(run);
t.start();
Runnable run = new Runnable{
void run(){
addObjects(objects, new OnQueryListener{
void begin(){
}
void end(){
handler.post(new Runnable{
void run(){
// On your main UI
}
}
}
}
}
}
It's not something i've tested on real code, just something at the top of my head.
I'm creating a basic game, and I can load images fine. Now, I'm trying to load sounds but I keep getting NullPointerExceptions. I'm 100% sure the path is correct, I've tried loading more then one sounds and I always get this error. I've only been able to use it once.
Here is my sound bank:
public class SoundBank {
public static Audio oggEffect;
public SoundBank () {
try {
oggEffect = AudioLoader.getAudio("OGG", ResourceLoader.getResourceAsStream("Res/ping_pong_8bit_plop.ogg"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
And my execution code:
else if (Keyboard.isKeyDown(Keyboard.KEY_8)) {
SoundBank.oggEffect.playAsSoundEffect(1.0f, 1.0f, true);
}
I'm pretty sure it should be
/res/ping_pong...ogg
not
res/ping_pong...ogg
never initialize a static variable through constructor.
Method 1 (this prevent you from having to call new SoundBank(); to init):
public class SoundBank {
public static Audio oggEffect;
static {
try {
oggEffect = AudioLoader.getAudio("OGG", ResourceLoader.getResourceAsStream("Res/ping_pong_8bit_plop.ogg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Method 2 (I have it working like this):
public class SoundUtils {
public static void playSound(String res) {
try {
Audio a = AudioLoader.getAudio("OGG", ResourceLoader.getResourceAsStream("res/sfx/" + res + ".ogg"));
a.playAsSoundEffect(1, 1, false);
} catch (IOException e) {
e.printStackTrace();
//You don't need this.
LoggerSys.get().getCurrentLogger().log("wtf i haz dun err0rz (" + e.toString() + ")");
}
}
}
EDIT: Oh, and make sure the path is correct (Res/... instead of res/... etc.)
I'm new in Libgdx and I'm getting trouble on using a database on my game.
I searched for a tutorial on how to make SQLite work on both Android and Desktop applications using Libgdx but I didn't found a easy one.
The last time I used a database in Android, I created a class that extends from SQLiteOpenHelper.
Is there a simple way to do the same using Libgdx? Or at least, can anyone point me to a step-by-step tutorial or something similar?
EDIT
I forgot to say that I'm looking for something that let me manage versions like SQLiteOpenHelper. In other words, I want to recreate my database in Android on apk installation, when I change the version of my DB on code.
SOLUTION
Following #42n4 answer, I managed how to connect to SQLite Database using SQLiteOpenHelper on Android Application and JDBC on Desktop Application.
First, I created a "common class" for both Desktop and Android Applications:
//General class that needs to be implemented on Android and Desktop Applications
public abstract class DataBase {
protected static String database_name="recycling_separation";
protected static DataBase instance = null;
protected static int version=1;
//Runs a sql query like "create".
public abstract void execute(String sql);
//Identical to execute but returns the number of rows affected (useful for updates)
public abstract int executeUpdate(String sql);
//Runs a query and returns an Object with all the results of the query. [Result Interface is defined below]
public abstract Result query(String sql);
public void onCreate(){
//Example of Highscore table code (You should change this for your own DB code creation)
execute("CREATE TABLE 'highscores' ('_id' INTEGER PRIMARY KEY NOT NULL , 'name' VARCHAR NOT NULL , 'score' INTEGER NOT NULL );");
execute("INSERT INTO 'highscores'(name,score) values ('Cris',1234)");
//Example of query to get DB data of Highscore table
Result q=query("SELECT * FROM 'highscores'");
if (!q.isEmpty()){
q.moveToNext();
System.out.println("Highscore of "+q.getString(q.getColumnIndex("name"))+": "+q.getString(q.getColumnIndex("score")));
}
}
public void onUpgrade(){
//Example code (You should change this for your own DB code)
execute("DROP TABLE IF EXISTS 'highscores';");
onCreate();
System.out.println("DB Upgrade maded because I changed DataBase.version on code");
}
//Interface to be implemented on both Android and Desktop Applications
public interface Result{
public boolean isEmpty();
public boolean moveToNext();
public int getColumnIndex(String name);
public float getFloat(int columnIndex);
[...]
}
}
Then, I created a DatabaseDesktop Class for Desktop Application:
public class DatabaseDesktop extends DataBase{
protected Connection db_connection;
protected Statement stmt;
protected boolean nodatabase=false;
public DatabaseDesktop() {
loadDatabase();
if (isNewDatabase()){
onCreate();
upgradeVersion();
} else if (isVersionDifferent()){
onUpgrade();
upgradeVersion();
}
}
public void execute(String sql){
try {
stmt.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
public int executeUpdate(String sql){
try {
return stmt.executeUpdate(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
public Result query(String sql) {
try {
return new ResultDesktop(stmt.executeQuery(sql));
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
private void loadDatabase(){
File file = new File (database_name+".db");
if(!file.exists())
nodatabase=true;
try {
Class.forName("org.sqlite.JDBC");
db_connection = DriverManager.getConnection("jdbc:sqlite:"+database_name+".db");
stmt = db_connection.createStatement();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void upgradeVersion() {
execute("PRAGMA user_version="+version);
}
private boolean isNewDatabase() {
return nodatabase;
}
private boolean isVersionDifferent(){
Result q=query("PRAGMA user_version");
if (!q.isEmpty())
return (q.getInt(1)!=version);
else
return true;
}
public class ResultDesktop implements Result{
ResultSet res;
boolean called_is_empty=false;
public ResultDesktop(ResultSet res) {
this.res = res;
}
public boolean isEmpty() {
try {
if (res.getRow()==0){
called_is_empty=true;
return !res.next();
}
return res.getRow()==0;
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
public boolean moveToNext() {
try {
if (called_is_empty){
called_is_empty=false;
return true;
} else
return res.next();
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
public int getColumnIndex(String name) {
try {
return res.findColumn(name);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
public float getFloat(int columnIndex) {
try {
return res.getFloat(columnIndex);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
[...]
}
}
And a DatabaseAndroid for Android Application
public class DatabaseAndroid extends DataBase{
protected SQLiteOpenHelper db_connection;
protected SQLiteDatabase stmt;
public DatabaseAndroid(Context context) {
db_connection = new AndroidDB(context, database_name, null, version);
stmt=db_connection.getWritableDatabase();
}
public void execute(String sql){
stmt.execSQL(sql);
}
public int executeUpdate(String sql){
stmt.execSQL(sql);
SQLiteStatement tmp = stmt.compileStatement("SELECT CHANGES()");
return (int) tmp.simpleQueryForLong();
}
public Result query(String sql) {
ResultAndroid result=new ResultAndroid(stmt.rawQuery(sql,null));
return result;
}
class AndroidDB extends SQLiteOpenHelper {
public AndroidDB(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
public void onCreate(SQLiteDatabase db) {
stmt=db;
DatabaseAndroid.this.onCreate();
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
stmt=db;
DatabaseAndroid.this.onUpgrade();
}
}
public class ResultAndroid implements Result{
Cursor cursor;
public ResultAndroid(Cursor cursor) {
this.cursor=cursor;
}
public boolean isEmpty() {
return cursor.getCount()==0;
}
public int getColumnIndex(String name) {
return cursor.getColumnIndex(name);
}
public String[] getColumnNames() {
return cursor.getColumnNames();
}
public float getFloat(int columnIndex) {
return cursor.getFloat(columnIndex);
}
[...]
}
}
Finally, I changed the Main Classes of both Android and Desktop Applications:
public class Main extends AndroidApplication {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initialize(new MyGame(new DatabaseAndroid(this.getBaseContext())), false);
}
}
public class Main {
public static void main(String[] args) {
new LwjglApplication(new MyGame(new DatabaseDesktop()), "Example", MyGame.SCREEN_WIDTH, MyGame.SCREEN_HEIGHT,false);
}
}
Note that:
I made a version management like the one that happens in SQLiteOpenHelper using the PRAGMA user_version. This way, I just change the version of the DataBase class when I need to upgrade it.
I didn't put all the methods that I made on Result but, I put the ones that I think that are more important.that are more important.
There is an extension (called gdx-sqlite) that I wrote which will do most of the work you require. Latest build of this extension can be downloaded from here. The source code and read me are located at: https://github.com/mrafayaleem/gdx-sqlite
This extension currently supports Android and Desktop platforms. Also, there is no support to open databases located in the assets folder of the Android app. However, this is a pending feature and will be added soon.
Follow the instructions in read me to setup your projects for database handling. Following is an example code:
package com.mrafayaleem.gdxsqlitetest;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.sql.Database;
import com.badlogic.gdx.sql.DatabaseCursor;
import com.badlogic.gdx.sql.DatabaseFactory;
import com.badlogic.gdx.sql.SQLiteGdxException;
public class DatabaseTest {
Database dbHandler;
public static final String TABLE_COMMENTS = "comments";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_COMMENT = "comment";
private static final String DATABASE_NAME = "comments.db";
private static final int DATABASE_VERSION = 1;
// Database creation sql statement
private static final String DATABASE_CREATE = "create table if not exists "
+ TABLE_COMMENTS + "(" + COLUMN_ID
+ " integer primary key autoincrement, " + COLUMN_COMMENT
+ " text not null);";
public DatabaseTest() {
Gdx.app.log("DatabaseTest", "creation started");
dbHandler = DatabaseFactory.getNewDatabase(DATABASE_NAME,
DATABASE_VERSION, DATABASE_CREATE, null);
dbHandler.setupDatabase();
try {
dbHandler.openOrCreateDatabase();
dbHandler.execSQL(DATABASE_CREATE);
} catch (SQLiteGdxException e) {
e.printStackTrace();
}
Gdx.app.log("DatabaseTest", "created successfully");
try {
dbHandler
.execSQL("INSERT INTO comments ('comment') VALUES ('This is a test comment')");
} catch (SQLiteGdxException e) {
e.printStackTrace();
}
DatabaseCursor cursor = null;
try {
cursor = dbHandler.rawQuery("SELECT * FROM comments");
} catch (SQLiteGdxException e) {
e.printStackTrace();
}
while (cursor.next()) {
Gdx.app.log("FromDb", String.valueOf(cursor.getString(1)));
}
try {
dbHandler.closeDatabase();
} catch (SQLiteGdxException e) {
e.printStackTrace();
}
dbHandler = null;
Gdx.app.log("DatabaseTest", "dispose");
}
}
http://marakana.com/techtv/android_bootcamp_screencast_series.html
Class 4, Part 1: Android Bootcamp - statusData, for libgdx: http://code.google.com/p/libgdx-users/wiki/SQLite
EDIT:
I should mention about two new courses about libgdx games at Udacity:
https://github.com/udacity/ud405
https://github.com/udacity/ud406