Storing application database schema - android

In example apps database is in most cases single table, so db schema is stored in static variable.
Storing large schema in seperate file is more friendly for me.
How can I do that? I thought about using resources (R.strings.db_schema) but probably there is a better way.
Could somebody give me any advice?

You could put the schema data in a raw file under res/raw. Then you can just load and parse that file the first time.

The way I do is to have a class per table, named after the table with "Table" suffix (e.g. PlayerTable or EventTable).
These classes contain all the static variable for the table name and all the field names, and they also contain two static methods:
public static void onCreate(SQLiteDatabase database)
public static void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
So that my SQLiteOpenHelper can just call all of them, without having hundreds of static variables with all the fields and create queries. E.g:
#Override
public void onCreate(SQLiteDatabase database) {
PlayerTable.onCreate(database);
EventTables.onCreate(database);
..... any other table you have .....
}
This class is then injected into all my data access objects (select / update / insert queries). For them I have dedicated classes that contain all my methods, by functionality (e.g. EventHandlingDAO for all the queries that deal with event handling).
And finally, theses DAO are injected into the activities that need them, when needed.
EDIT: A few more details about my code:
My main objects are the DAO (data access objects), in which I have methods like:
// in EventHandlingDAO:
public void addEvent(Event event) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
try {
database.execSQL("INSERT INTO " + EventTable.EVENT_TABLE_NAME + " (...."); // list of fields and values
} finally {
database.close();
}
}
public List<Event> getAllEvents() {
final List<Event> result = new ArrayList<Event>();
SQLiteDatabase database = databaseHelper.getReadableDatabase();
try {
final Cursor cursor = database.rawQuery("SELECT " + EventTable.KEY_NAME + ", " + EventTable.KEY_DATE_AS_STRING + " FROM " + EventTable.TABLE_NAME, null);
cursor.moveToFirst();
// ... rest of the logic, that iterates over the cursor, creates Event objects from the cursor columns and add them to the result list
return result;
} finally {
database.close();
}
}
So in that DAO, I have my databaseHelper object, which instanciates my class that extends SQLiteOpenHelper with the methods I talked about above.
And of course, I have interfaces to all my DAO, so that I can inject a Stub or mocked implementation in my tests (or experiment with different implementations if I want to try another solution based on SharedPreference for example)
And the code for my PlayerTable table:
public static void onCreate(SQLiteDatabase database) {
database.execSQL(TABLE_CREATE); // TABLE_CREATE is my "CREATE TABLE..." query
}
public static void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
// A bit blunt, that destroys the data unfortunately, I'll think about doing something more clever later ;)
database.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(database);
}

Related

ORMLite dropping data when adding a column to the table

In my Android app, I'm using ORMLite to store data into local database, and when adding a column to that database using onUpgrade() method, I'm getting all the data of that table to be erased.
I'm using upgrade schema way mentioned in ORMLite documentation:
private static final int DATABASE_VERSION = 10;
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int oldVer, int newVer) {
try {
if(oldVer < 10){
getGuardiansDao().executeRaw("ALTER TABLE `messages` ADD COLUMN updated_by TEXT;");
getGuardiansDao().executeRaw("ALTER TABLE `messages` ADD COLUMN updated_by_time TEXT;");
}
} catch (SQLException e) {
Log.e(DBManager.class.getName(), "Unable to upgrade database from version " + oldVer + " to new "
+ newVer, e);
}
}
And in the class assigned to that table:
#DatabaseTable(tableName = "messages")
public class Message extends Object implements Parcelable{
.
.
.
#DatabaseField
private String updatedBy;
#DatabaseField
private String updatedByTime;
}
Now after executing that it erases all the data stored in the table messages and I don't have any clue why that is happening.
Now after executing that it erases all the data stored in the table messages and I don't have any clue why that is happening.
Certainly the code that you've posted won't erase the table and ORMLite doesn't do that automatically or anything. Is there any chance the onCreate(...) method is being called instead for some reason?
There are many ways to debug this but you could log the contents of the table using raw statements in the onUpgrade(...) method to ensure that the table is being correctly built. Then you might be able to detect when it has been cleared.

Database in android studio [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm a windows phone developer and newly I started developing android apps using android studio.
I need to create a database and store in it values and retrieve the updated values on screen, so I need help in:
Creating the database.
How to show values from the database on screen?
to create database , you need to extend SQLiteOpenHelper and need a constructor that takes Context.
lets say you name this class DBOperator. The table creation process will look something like this ,
public class DbOperator extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "DB_NAME";
protected static final String FIRST_TABLE_NAME = "FIRST_TABLE";
protected static final String SECOND_TABLE_NAME = "SECOND_TABLE";
public static final String CREATE_FIRST_TABLE = "create table if not exists "
+ FIRST_TABLE_NAME
+ " ( _id integer primary key autoincrement, COL1 TEXT NOT NULL, COL2 TEXT NOT NULL,COL3 TEXT, COL4 int, COL5 TEXT,"
+ "COL6 TEXT,COL7 REAL, COL8 INTEGER,COL9 TEXT not null);";
public static final String CREATE_SECOND_TABLE = "create table if not exists "
+ SECOND_TABLE_NAME+.........
public DbOperator(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_SFIRST_TABLE);
db.execSQL(CREATE_SECOND_TABLE);
//db.close();
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//THIS WILL BE EXECUTED WHEN YOU UPDATED VERSION OF DATABASE_VERSION
//YOUR DROP AND CREATE QUERIES
}
}
Now your data manipulation class ( add, delete , update ) will look something like this ,
public class FirstTableDML extends DbOperator {
public FirstTableDML(Context context) {
super(context);
}
private static final String COL_ID = "_id";
private static final String COL1 = "COL1";
private static final String COL2 = "COL2";
........
.......
public void deleteFirstTableDataList(List<FirstTableData> firstTableDataList) {
for (FirstTableData data : firstTableDataList)
deleteFirstTableDetailData(data);
}
public void deleteFirstTableDetailData(FirstTableData item) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(FIRST_TABLE_NAME, item.getId() + "=" + COL_ID, null);
db.close();
}
/**this method retrieves all the records from table and returns them as list of
FirstTableData types. Now you use this list to display detail on your screen as per your
requirements.
*/
public List< FirstTableData > getFirstTableDataList() {
List< FirstTableData > firstTableDataList = new ArrayList< FirstTableData >();
String refQuery = "Select * From " + FIRST_TABLE_NAME;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(refQuery, null);
try {
if (cursor.moveToFirst()) {
do {
FirstTableData itemData = new FirstTableData();
itemData.setId(cursor.getInt(0));
itemData.setCol1(cursor.getString(1));
itemData.setCol2(cursor.getInt(2));
.....
.....
firstTableDataList.add(itemData);
} while (cursor.moveToNext());
}
} finally {
db.close();
}
Collections.sort(itemDataList);
return itemDataList;
}
public int addFirstTableData(FirstTableData data) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COL1, data.getCol1());
values.put(COL2, data.getCol2());
.....
.....
long x=db.insert(FIRST_TABLE_NAME, null, values);
db.close();
return (int)x;
}
public void updateItemDetailData(FirstTableData data) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COL1, data.getCol1());
values.put(COL2, data.getCol2());
values.put(COL3, data.getCol3());
.....
.....
db.update(FIRST_TABLE_NAME, values, COL_ID + "=" + data.getId(), null);
db.close();
}
}
P.S : *Data class are POJO data class representing the corresponding table.
Since you said you are not totally new to these, I have not provided any helper comments as most of the method names are self explanatory.
Hope it helps you to get started.
To creating a database for Android application, there are 2 ways:
Create database and tables using Code
Use existing database
1) Create database and tables using Code
In this scenario, you have to write a class and code to create database and tables for it. You have to use different classes and interfaces like SQLiteOpenHelper, SQLiteDatabase, etc. Check answer posted by Jimmy above.
2) Use existing database
In this scenario, you can use your existing sqlite database inside your android application. You have to place database file inside assets folder and write a code to copy that existing database on to either internal or external storage.
Regarding best scenario, I would say it's depend on the application functionality and nature, if your database is small then you should go with 1st scenario and if your database is large with many tables then you should go with 2nd scenario because you would be creating database using any GUI based SQLite browser and which would help you to make less mistakes. (When I say less mistakes using GUI, believe me there are chances of creating tables by code).
How to show values from the database on screen?
For that you have to write a SQL query which gives you Cursor in return which is a set of resultant data, so you have to iterate through the cursor data and prepare a set of data in terms of ArrayList or Array or HashMap.
You can display this set of data in ListView or GridView.
P.S. I am not posting links to any tutorials or examples as there are plenty of information/examples available on web, so suggesting you to search around the given points.
A good way to start is to read about Storage Options on the official Android documentation website: http://developer.android.com/guide/topics/data/data-storage.html

Android dev: Creating a sqlite database for word games, no user inputs

I have a simple game where users guess words. Now, I'm thinking using database to store these words to be guessed.
My problem is the tutorials that are available in the web show how to create a database and save user inputs to that database. They create, for example, a DBHelper.java in src, extends it to SQLiteOpenHelper, override the methods. Back to a specific activity, create an instance of DBHelper, then create the db, open the writable, insert user inputs, close db.
But what I think I only need to do is create a database, insert words in it, then make my app retrieve words from this database.
Am i just wondering if what i'm planning to do is right:
1. create a DBHelper.java in src, extends the class to SQLiteOpenHelper
2. define needed Strings like name of database etc.
3. Create a constructor and override the onCreate and onUpgrade methods
4. CREATE A LOADWORDS METHOD this is where i will insert my words to the database.
5. on my main activity(the first screen on my app) I will create an instance of DBHelper and call the onCreate and loadWords method.
// you would want an onCreate and onUpgrade method for best practices,, here's a partial look of what you want...
public class DBManager extends SQLiteOpenHelper
{
static final String TAG = "DBManager";
static final String DB_NAME = "words.db";
static final int DB_VERSION = 1;
static final String TABLE = "words_table";
static final String C_ID = "id";
static final String C_WORD = "word";
public DBManager(Context context)
{
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
String sql = "CREATE TABLE " + TABLE + " ("
+ C_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ C_WORD + " TEXT)";
db.execSQL(sql);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSQL("DROP TABLE IF EXISTS " + TABLE);
onCreate(db);
}
//**** Code Insert Word and Retrieve Word Methods *****//
//**** End Code Insert Word and Retrieve Word Methods *****//
}

Fetch data from existing sqlite database

I am having an existing sqlite database. I am developing an android app and I want to connect it with this existing sqlite DataBase.
Problem 1:
I have already included the sqlite database in my project via "DDMS push database function" as per my instructor's advise. Now I want to fetch the data from database, do I need to use SQLiteOpenHelper. If yes, how to use it and what will be coded in onCreate(SQLiteDatabase db) function and onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) function as we already have the Database with us, we don't really need to create it.
Problem 2:
What should be done to simply fetch the required data from the existing database.
Being a newbie, I am quite confused, can someone please explain these concepts and guide me to overcome this issue. Any help would be appreciated.
I have seen a tutorial also for this purpose as sugggested by #TronicZomB, but according to this tutorial (http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/), I must be having all the tables with primary key field as _id.
I have 7 tables namely destinations, events, tour, tour_cat, tour_dest, android_metadata and sqlite_sequence. Out of all, only tour_dest is not fulfilling the conditions of having a primary key named as _id. How to figure out this one?
Following is the screenshot of table which is lacking the primary key field necessary for binding id fields of database tables.
The onCreate and onUpgrade methods will be empty since you already have the database. There is a great tutorial on how to achieve this here.
You could then access the database like such (example):
public ArrayList<String> getValues(String table) {
ArrayList<String> values = new ArrayList<String>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT value FROM " + table, null);
if(cursor.moveToFirst()) {
do {
values.add(cursor.getString(cursor.getColumnIndex("value")));
}while(cursor.moveToNext());
}
cursor.close();
db.close();
return values;
}
Unless you are very comfortable with queries, databases, etc. I highly recommend you use http://satyan.github.io/sugar/ , it will also remove a lot of the boiler plate code required to do sqlite in Android
1. If DB already exists, onCreate will not invoke. onUpgrade will be invoked only if you will change DB version. onUpgrade you should to use if there some changes in your APP's database, and you have to make migration on new structure of data smoothly.
public class DbInit extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "name";
private static final int DATABASE_VERSION = 3;
private static final String DATABASE_CREATE = "create table connections . .. . ...
public DbInit(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (isChangeFromToVersion(1, 2, oldVersion, newVersion)) {
//Execute UPDATE here
}
}
private boolean isChangeFromToVersion(int from, int to, int oldVersion, int newVersion ) {
return (from == oldVersion && to == newVersion);
}
....
2. Simple example how to open connection to DB and get cursor object.
public class DAO {
private SQLiteDatabase database;
private DbInit dbHelper;
public ConnectionDAO(Context context) {
dbHelper = new DbInit(context);
}
public void open() throws SQLException {
database = dbHelper.getWritableDatabase();
}
public Connection getConnectionById(long id) {
Cursor cursor = null;
try {
open();
cursor = database.query(DbInit.TABLE_CONNECTIONS, allColumns, DbInit.COLUMN_ID + " = '" + id + "'", null, null, null, null);
if (!cursor.moveToFirst())
return null;
return cursorToConnection(cursor);
} finally {
if (cursor != null)
cursor.close();
close();
}
}
private Connection cursorToConnection(Cursor cursor) {
Connection connection = new Connection();
connection.setId(cursor.isNull(0) ? null : cursor.getInt(0));
connection.setName(cursor.isNull(1) ? null : cursor.getString(1));
.....
.....
return connection;
}

onCreate not being called after getWritableDatabase/getReadableDatabase

My app's got a database with three tables in it: one to store the names of the people it tracks, one to track an ongoing event, and one - for lack of a better term - for settings.
I load the first table when the app starts. I ask for a readable database to load in members to display, and later I write to the database when the list changes. I've had no problems here.
The other two tables, however, I can't get to work. The code in the helper classes is identical with the exception of class names and column names, and (at least until the point where I try to access the table) the code to use the table is nearly identical as well.
Here's the code for my helper class (I've got a separate helper for each table, and as I said, it's identical except for class names and columns):
public class db_MembersOpenHelper extends SQLiteOpenHelper
{
public static final String TABLE_NAME = "members_table";
public static final String[] COLUMN_NAMES = new String[] {
Constants.KEY_ID,
"name",
"score"
};
private static final String TABLE_CREATE = "CREATE TABLE " + TABLE_NAME + " ("
+ COLUMN_NAMES[0] + " INTEGER PRIMARY KEY autoincrement, "
+ COLUMN_NAMES[1] + " TEXT, "
+ COLUMN_NAMES[2] + " INTEGER);";
public db_MembersOpenHelper(Context context)
{
super(context, Constants.DATABASE_NAME, null, Constants.DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) { db.execSQL(TABLE_CREATE); }
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
Log.w("TaskDBAdapter", "Upgrading from version " + oldVersion + " to " + newVersion + ".");
// Do nothing. We do not have any updated DB version
}
}
Here's how I use it successfully:
db_MembersOpenHelper membersDbHelper = new db_MembersOpenHelper(this);
SQLiteDatabase membersDb = membersDbHelper.getReadableDatabase();
Cursor membersResult = membersDb.query(TABLE_NAME, null, null, null, null, null, null);
members = new HashMap<String, Integer>();
membersResult.moveToFirst();
for(int r = 0; r < membersResult.getCount(); r++)
{
members.put(membersResult.getString(1), membersResult.getInt(2));
membersResult.moveToNext();
}
membersDb.close();
And here's where it fails:
db_PlayersOpenHelper playersDbHelper = new db_PlayersOpenHelper(this);
final SQLiteDatabase playersDb = playersDbHelper.getWritableDatabase();
if(newGame)
{
for(String name : players)
{
ContentValues row = new ContentValues();
row.put(COLUMN_NAMES[1], name);
row.put(COLUMN_NAMES[2], (Integer)null);
playersDb.insert(TABLE_NAME, null, row);
}
}
The first one works like a charm. The second results in ERROR/Database(6739): Error inserting achievement_id=null name=c
android.database.sqlite.SQLiteException: no such table: players_table: , while compiling: INSERT INTO players_table(achievement_id, name) VALUES(?, ?);
...
I did do some testing, and the onCreate method is not being called at all for the tables that aren't working. Which would explain why my phone thinks the table doesn't exist, but I don't know why the method isn't getting called.
I can't figure this out; what am I doing so wrong with the one table that I accidentally did right with the other?
I think the problem is that you are managing three tables with with three helpers, but only using one database. SQLiteOpenHelper manages on database, not one table. For example, it checks to see whether the database, not table, exists when it starts. It already does, so onCreate() does not fire.
I would manage all tables with one helper.
Let me see if I get this right. You are trying to create one database with three tables. But when you create the database, you create just one table; you are somehow instantiating the same database at a different place and wonder why its onCreate method doesn't get called. Is this a correct interpretation?
My strategy would be to try and create all three tables in the single onCreate() method.
If you are working with multiple tables, then you have to create all of the tables at once. If you have run your application first and later you update your database, then it will not upgrade your DB.
Now delete your application, then run it again.
There is one more solution but it is not proper. You can declare onOpen method in which you can call onCreate. And add IF NOT EXISTS before table name in your create table string. – Sourabh just now edit

Categories

Resources