green dao update column on play store update has taken place - android

this is my Generator class
public class Generator {
public static void main(String[] args) throws Exception {
Schema schema = new Schema(1, "app.abc.db.dao");
createAbcDB(schema);
}
private static void createAbcDB(Schema schema) throws IOException, Exception {
Entity abc = schema.addEntity("Abc");
abc.addIdProperty();
abc.addShortProperty("name");
}
}
This is the code where i get abc dao from dao session. This works fine.
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(SurveyActivity.this, "abc.db", null);
SQLiteDatabase db = devOpenHelper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
DaoSession daoSession = daoMaster.newSession(IdentityScopeType.None);
abcDao = daoSession.getAbcDao();
I added one more column
abc.addShortProperty("email");
to createAbcDB in generator to new version of app. Once users get updated they are getting sql exception saying no column found. Because i am calling on new login
dropAllTables(db, true);
onCreate(db);
But problem is i have given one time login that user will always come to landing screen on upgrade from play store. So i don't know whether the user is upgraded app or not in order to drop and create all tables.
So my question is how to know my table has altered?

Each time that you do a significant modification like this, you have to update de Schema version number:
Schema schema = new Schema(2, "app.abc.db.dao");
This way, in the OpenHelper present in the DaoMaster, or in the SQLiteOpenHelper taht you're using, you can control this changes in onUpgrade() function:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
dropAllTables(db, true);
onCreate(db);
}

Related

GreenDao - Android - OnUpgrade not being called (Encrypted Database)

I'm using GreenDao 3.2.2 for my DB,
On my first run on creating Entities via #tags everything worked ok.
Now I am editing the gradle schema to higher versions because I added some props to a table:
greendao {
schemaVersion 4
}
However the OpenHelper onUpgrade method is never called, thus my project is always crashing because some columns are not found.
Application class
//Init DB
UpgradeHelper helper = new UpgradeHelper(this, ENCRYPTED ? "db-encrypted" : "db", null);
Database db = ENCRYPTED ? helper.getEncryptedWritableDb("app-cipher") : helper.getWritableDb();
daoSession = new DaoMaster(db).newSession();
OpenHelper class
public class UpgradeHelper extends DaoMaster.OpenHelper {
public UpgradeHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//never gets called
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion);
//do migrations
}
}
am I missing something?
Got it!!! After hours of searching and reading GreenDAO code I understood the problem.
The problem is that getEncryptedWritableDb creates another kind of DB that does not extends SQLiteDatabase. So even when the EncryptedHelper gets the onUpgrade method, my helper class didn't catch it because it fell into another signature.
The solution was simply using the other signature that receives a DAO Database interface:
public void onUpgrade(Database db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by migrating all tables data");
//do migration
}
of course I needed to update all my Migration methods to receive a Database object instead of a StandardDatabase

GreenDAO not respecting #Unique fields

First time implementing GreenDAO. Been reading a lot of the other questions and I feel I've followed all of them.
My simple Entity:
#Entity(
indexes = {
#Index(value = "searchTerm", unique = true)
}
)
public class SearchTerm
{
#Id private Long id;
// #Unique have also tried this
// #Index(unique = true) have also tried this
private String searchTerm;
private Date date;
}
I then insert into the table using searchTermDao.insertOrReplace(searchTerm). The problem is it will store multiple entries where the searchTerm is exactly the same. What am I doing wrong?
private SearchViewQueryTextEvent storeSearchTerm(SearchViewQueryTextEvent queryTextEvent)
{
SearchTerm searchTerm = new SearchTerm();
searchTerm.setSearchTerm(queryTextEvent.queryText().toString());
searchTerm.setDate(new Date());
searchTermDao.insertOrReplace(searchTerm);
Log.d(TAG, "Stored new search term: " + searchTerm.getSearchTerm());
return queryTextEvent;
}
SOLUTION:
Thanks to Luiz in comments I just upgraded the database on initialisation:
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(mContext, "search-db");
helper.onUpgrade(helper.getWritableDatabase(), 1, 2);
Database db = helper.getWritableDb();
return new DaoMaster(db).newSession();
.onUpgrade() only needed to be called once.
I faced the same problem and after reviewing the logs I realized that the database was not being updated after I applied the annotation #Unique.
To fix this issue, try to increase the database version inside your class that extends SQLiteOpenHelper and drop your table inside your onUpgrade() method.
private static final int VERSION = 2; //+ one number
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS" + table_name);
onCreate(db);
}

Manually executing sql query in Android

I already have a database in my app using a 3rd party library. The library doesn't seem to have drop table functionality. So I was thinking to directly change it using SQLiteOpenHelper API. Is this possible?
I have created a class that extends SQLiteOpenHelper and give it the same db name as the one used in the library.
public class SqliteDatabaseHelper extends SQLiteOpenHelper {
// Database Info
private static final String DATABASE_NAME = "myDatabase";
private static final int DATABASE_VERSION = 1;
private Context context;
public SqliteDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
L.w("old: " + oldVersion + ", " + "new: " + newVersion);
if (oldVersion != newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + "deals_latest");
onCreate(db);
L.w("drop it like it's hot");
}
}
}
And I initialize it in Application class, just to see if it reflects the db class I created.
SQLiteDatabase db = new SqliteDatabaseHelper(this).getReadableDatabase();
L.w("version: " + db.getVersion());
L.w("path: " + db.getPath());
SqliteDatabaseHelper helper = new SqliteDatabaseHelper(this);
helper.onUpgrade(db, 1, 2); // this line suppose to invoke the drop table query
When running the app, onUpgrade() method doesn't seem to be called.
Mind you, I have never had any experience in using the native SQLite helper, so I have no idea what is going on here. My objective is just to see if the query in onUpgrade is executed or not. But the table still exists in the database.
How do I get around this?
The SQLiteOpenHelper class helps to manage versions of your own database.
It does not make sense to use it for a database that is managed by third-party code.
Just open the database directly with openDatabase().

Unable to open databse file sql lite android

I'm trying to to create a database and insert some data into it but this doesn't seem to be working. Can anybody tell me what's wrong in my implementation? Here is my code for the database. Thank you.
SQLiteDatabase db = null;
db.openOrCreateDatabase("order", null);
db.execSQL("CREATE TABLE IF NOT EXISTS order ( id INTEGER PRIMARY KEY AUTOINCREMENT, Name VARCHAR, Price INTEGER)");
db.execSQL("INSERT INTO order (Name, Price) VALUES ('Paneer Tikka', '100')");
SQLiteDatabase db = null;
db.openOrCreateDatabase.. will result in NullPointerException. You need to assign SQLLiteDatabase instance to db and then call openOrCreateDatabase on db.
Another issue is, 100 is integer, don't need in single quotes.
db.execSQL("INSERT INTO order (Name, Price) VALUES ('Paneer Tikka', 100)");
There is a really nice tutorial supplied by google. It take you through how to do the basics with the SQLite database.
http://developer.android.com/resources/tutorials/notepad/index.html
I would suggest going through that.
In that tutorial is suggests using a SQLHelper inner class something like this
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(DATABASE_CREATE_CELEBS);
db.execSQL(DATABASE_CREATE_CHECKINS);
Log.i("dbCreate", "must have worked");
} catch (Exception e) {
Log.i("dbCreate", e.toString());
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS celebs");
db.execSQL("DROP TABLE IF EXISTS checkins");
onCreate(db);
}
}
Then to get a new database you can call
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
You need to learn about SQLiteOpenHelper. Ask Google for some tutorials.
Incredibly Sqlite has much better performance "in transation" on inserts without transaction. I particularly, massive use transaction processes, or failure comes randomly at some point.

Best practices for creating a SQLite database on Android

I have read through a lot of the posts on copying the database file over from the assets or raw folders to the /data/data/APP/databases folder, but that would leave two copies of the DB on the device taking up valuable space. I am thinking of building a solution with a slightly smaller footprint and allowing for more flexible schema management by storing the database SQL creation text file in the raw folder and using the standard on_create / on_update process in the DBhelper class. However I am a little confused because the examples that copy the database over bypass the on_create and on_update methods.
Is this the recommended way if you are not building the db from strings in the code?
My solution would simulate the running scripts from code method by having the scripts all in one file. The reason I am looking at building the db this way is that my DB will have close to 100 tables when the application is complete, so I need the schema to be manageable.
Any guidance is welcome as I am still learning the best practices and patterns for Android.
Here is an example of my code:
public class DatabaseHelper extends SQLiteOpenHelper {
private final String DATABASE_NAME = "mydb";
private final int DATABASE_VERSION = 1;
private final Context myCtx;
private String DATABASE_CREATE_SCRIPT = null;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
DATABASE_CREATE_SCRIPT = getLoadFile();
// Create all tables and populate the lookup tables
db.execSQL(DATABASE_CREATE_SCRIPT);
db.execSQL(VIEW_CREATE_V_PERSON);
}
private String getLoadFile(){
InputStream inputStream = myCtx.getResources().openRawResource(resIdofmyfile);
InputStreamReader inputreader = new InputStreamReader(inputStream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line;
StringBuilder text = new StringBuilder();
try {
while (( line = buffreader.readLine()) != null) {
text.append(line);
text.append('\n');
}
} catch (IOException e) {
// We have an error to look up
return null;
}
return text.toString();
}
/**
* onUpgrade will check the version of the database and update the database
* if a newer version is available.
*/
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Will set conditional upgrade checks
//Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which may destroy all old data");
db.execSQL("DROP TABLE IF EXISTS CONTEXT_LOAD");
db.execSQL("DROP TABLE IF EXISTS ISSUES");
db.execSQL("DROP TABLE IF EXISTS GOALS");
db.execSQL("DROP TABLE IF EXISTS PERSON");
db.execSQL("DROP VIEW IF EXISTS V_PERSON");
onCreate(db);
}
}
I guess it looks like a good practice. It's not very bad even if you create your database with code completely. Check out google's app for IO schedules it has a fairly big database creation part. It may lead you a way.
Here is the project home page, here is the database part
I use this application as a reference all the time it's like a work of art =)
Edit: Google updated the app so the old database link doesn't work.
I'm not really sure what your question is.
If you are asking if it's OK to create your DB from scratch using a text file containing a load of SQL CREATE statements then the answer is "yes".
Not only that but it's more flexible than distributing a pre-built DB within your APK as you could even download the 'schema' file or files from a network location. This allows you to update the schema dynamically at a central point.

Categories

Resources