I am using Ormlite for the first time and I am trying to setup my DatabaseHelper to insert rows after creating the database's tables. I am getting a getWritableDatabase called recursively error when I do.
Here is my onCreate:
public void onCreate(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource) {
try {
TableUtils.createTable(databaseType, connectionSource, User.class);
// Add test user
User test = new User("test", "12345");
getUserDao().create(test);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Unable to create databases", e);
}
}
The problem here was that #karnage was using an older version of ORMLite that had a bug with using the DAOs in the onCreate -- the pattern that he is using. This was fixed in version 4.6 (10/2010) and downloading and running the latest version works for him.
Here is the bug report:
https://sourceforge.net/tracker/?func=detail&aid=3117883&group_id=297653&atid=1255989
Here's the change log file to track new features and versions of ORMLite:
http://ormlite.com/changelog.txt
Related
I'm new to writing Xamarin Android by about 8 months.
I have an application up on the Google Play Store and when the application first installs, it creates the sqlite database from code.
I had to make a database table change, I added a few columns.
When the application does it's auto update, where/how do I tell it to drop the database and recreate it, or is it automatic? I'd expect not.
I'm not worried about the data, it will be re-downloaded.
I looked at Assets, creating a text file and reading a command from it, but I can't remove the asset, so that was a dead end.
Thanks for any help.
I like to use the built-in SQLiteOpenHelper class to maintain the Sqlite version numbers and providing the process for upgrading the database.
Using the builtin Android.Database.Sqlite.SQLiteOpenHelper you can easily use it to maintain your database version and if the version changes, delete the database and start fresh with a blank one (no tables/no data).
Remember: This is destructive "upgrade"...
public class SqliteOnVersionChangeCreateBlankDB : SQLiteOpenHelper
{
new const string DatabaseName = "myDBName";
const int DatabaseVersion = 1;
public SqliteOnVersionChangeCreateBlankDB(Context context) : base(context, DatabaseName, null, DatabaseVersion)
{
}
public override SQLiteDatabase ReadableDatabase
{
get
{
try
{
return base.ReadableDatabase;
}
catch
{
File.Delete(DatabaseName);
return base.WritableDatabase;
}
}
}
public override void OnCreate(SQLiteDatabase db)
{
Console.WriteLine($"{db}");
// You can create the DB tables/data here if needed...
// or use your favorite SQLite framework/library later...
}
public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
Console.WriteLine($"{db}:{oldVersion}:{newVersion}");
if (oldVersion < newVersion)
{
// Normally this is where you would alter the existing schema to the new version
// but this is a destructive upgrade.
db.Close();
File.Delete(db.Path);
}
}
}
Usage:
Starting with a version of 1 in the SQLiteOpenHelper subclass:
const int DatabaseVersion = 1;
Execute this code:
var sqliteHelper = new SqliteOnVersionChangeCreateBlankDB(this);
var db = sqliteHelper.ReadableDatabase;
db.Close();
You now have a blank database that is assigned version 1. It is empty, no tables/data so use your favorite Sqlite ORM/framework/library to create the tables and populate it with data...
Unless the database version changes, executing this code each time your app starts will not delete the existing database:
var sqliteHelper = new SqliteOnVersionChangeCreateBlankDB(this);
var db = sqliteHelper.ReadableDatabase;
db.Close();
Later on, App is updated and you also need to change the database, so assign a new version number that is higher the last, 2 in this case, to the database.
const int DatabaseVersion = 2;
Execute the same code as before:
var sqliteHelper = new SqliteOnVersionChangeCreateBlankDB(this);
var db = sqliteHelper.ReadableDatabase;
db.Close();
You now have a blank database again, but it is assigned version 2. Again your favorite Sqlite ORM/framework/library to create the tables and populate it with data...
First you might want to confirm your intended behavior. I would track your .sqlite file to see what happens to it given your workflow.
For the most part when an application is being updated from Google Play Store, all of your application's data will stay put. (As it is only updating and not uninstalling -> installing again)
You can mimic this behavior by applying the following in your debug environment:
If you find yourself in a scenario where you need to update the database to associate it with a new application update, then you would need some mechanism to compare your database version and if it is older than the application's code expects, you would then apply a schema change and potentially seed the database with initial information.
I have an Android app with a database with version 1.
I added a data column in one table and idi a migration into a new release.
The problem I have is how to do unit tests for this. I needed to check if old data are correct inserted in the new structure and the new column is added and filled in the right way.
How would I best do this? Thanks in advance.
You can create a test case that builds an old version of your database and then run your migration. Here is a stripped down example.
public class DbHelperTest extends AndroidTestCase {
private SQLiteDatabase db;
#Override
public void setUp() throws Exception {
super.setUp();
mContext = new RenamingDelegatingContext(getContext(), "db_helper_test_");
SQLiteDatabase.CursorFactory cursorFactory = new SQLiteDatabase.CursorFactory() {
#Override
public Cursor newCursor(final SQLiteDatabase db, final SQLiteCursorDriver masterQuery, final String editTable,
final SQLiteQuery query) {
return new SQLiteCursor(db, masterQuery, editTable, query);
}
};
db = SQLiteDatabase.create(cursorFactory);
createV14Db(db);
}
#Override
public void tearDown() throws Exception {
super.tearDown();
db.close();
}
private void createV14Db(SQLiteDatabase db) {
// Create tables and indices
db.execSQL(...);
// Create some data
db.execSQL(...);
}
public void testDbUpgrade() {
DbHelper dbHelper = new DbHelper(mContext);
dbHelper.onUpgrade(db, 14, 100);
// Check that things have been upgraded correctly
}
}
You have to test 2 scenarios :
User installs new version directly.
User is on an older version and upgrades to new version.
Testing the 2nd scenario is generally tricky.
What I generally do to test scenario 2 is :
Un-install the app from mobile.
I switch to code version of release 1 - Note that I use GIT and hence it is very easy to switch to older versions.
Run the app on device using Android studio.
Create some test data.
Switch to release 2 of code.
Start debugging in Android studio. At this point have break points in your DB upgrade methods to ensure that DB upgrade is smooth.
Continue with the rest of the testing.
I have uploaded an apk (version 1.0) with 22 tables in SQLite Database on Google Playstore.
Now i want to update database with 36 tables in new version (version 2.0) of application.
I am storing datebase at default location so when i press "Clear
data" in Application Manager, database is gonna deleted.
I just want to know how to delete old database (same as clear data) when user update new version?
Update:
If is there any solution for clear data while updating application from play store then also answered me.
Your help would be appreciated.
Thanks.
you can use this method to delete your database.
context.deleteDatabase(DATABASE_NAME);
You can also use this method to find your database path first and then delete that.
File myDb = context.getDatabasePath(DATABSE_NAME);
Boolean isDelete = myDb.delete();
The other solution is , if you want to update your database then just change your version number of database. onUpgrade() will automatically get called and your old database will be deleted and new database will be created.
Finally done with simple solution:
/** UPGRADE DATABASE **/
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "Database Version: OLD: "+ oldVersion + " = NEW: "+newVersion);
if(context.deleteDatabase(DATABASE_NAME))
Log.i(TAG, "Database Deleted....");
else
Log.i(TAG, "Database Not Deleted..");
}
Nice Question. Just follow the steps.
1) There are two methods that you override on Your Helper class
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion!=newVersion){
// Remove all old tables and crate new ones
}
}
2) create an object of Helper class.
MyOpenHelper dbHelper = new MyOpenHelper(this,"dbname", 1);
3) Now just increase the database version when you want to change the database.(Third argument in MyOpenHelper class. "1" is a database version).
4) When database version changes it will give you a callback in onUograde() method.
5) Remove all tables in onUpgrade() method and create new ones.
6) That's it.
EXPLANATION :
Your app version 1.1 is on google play and your database version is "1". Now you want to upload version 1.2 with new database. Just set database version "2" in your helper file. And check the the oldVersion and newVersion in onUpgrade() method if both are not same that means application updating and remove old tables and create new ones.
If you are using SQLiteOpenHelper just delete your tables in your onUpgrade method and recreate all your tables again. You should have not problems at all.
Check this out.
Hope it helps
Note: Be careful with database versions, if you are playing with your database numbers make sure you have the right number as your oldVersion or it will not work properly when you update your google play.
The obvious solution is to delete the old DB file when onUpgrade() is called and copy the new version over. Too bad it does not work. You get an error something like this:
Caused by: android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 1032)
SQLiteLog﹕ (1032) statement aborts at 4: [PRAGMA user_version = 2]
SQLiteLog﹕ (28) file unlinked while open: /data/data/my.package/databases/my_db.db
You don't need to delete the database, just copy over it using the method you've alady defined (copyDataBase), like this:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Toast.makeText(myContext, "onUpgrade called!", Toast.LENGTH_LONG).show();
if (oldVersion < newVersion) {
Log.v("Database Upgrade", "Database version higher, upgrading");
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error upgrading database");
}
}
}
wrok for me, thank
My app used ormlite to communicate with Sqlite database. There are many screens that get data from ormlite. The problem is I want to update the database in background without user' knowledge (it's transparent to user) and my app use some CursorAdapters and Loaders to get data. The behavior look like this: my app check if there is new version in server, it will download new db file from server, then change current db file from local by new server db file in ormlite helper. While update progress is happening, user can change screen or view data from db normally (I just use the select query)
I have searched some answer, they advised use onUpgrade method, but how can I apply this in my case, because I want to change completely the database file? And how can I switch the database while selecting data?
Here is my db helper:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public DatabaseHelper(Context context){
super(context, "document.sqlite", null, 1);
}
#Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
TableUtils.createTable(connectionSource, Category.class);
TableUtils.createTable(connectionSource, Book.class);
} catch (Exception ex) {
Ln.e(ex);
}
}
#Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion,
int newVersion) {
try{
TableUtils.dropTable(connectionSource, Category.class, true);
TableUtils.dropTable(connectionSource, Book.class, true);
// get new one
onCreate(db, connectionSource);
}catch(Exception ex){
Ln.e(ex);
}
}
Any help would be appreciated!
I had similar situation in my project in which I had to refresh database with new data after checking for new data.After trying so many methods Finally I reached at one solution.I do not know if that solution is optimal one but after testing it is working fine.
Solution is as follows:-
I am getting new data in json form so I am creating a new blank database with temp_original-database-name.db and then populating it with new data(in your case you have complete database downloading from server , so you do not need extra helper for creating temporary database). After this data is populated then I am renaming this database temp_original-database-name.db to original-database-name.db using file system methods.
I have done testing and original helper instance used for original database still exists even after still second rename of database operation.and everything works fine.
Hope this can help.Please tell me if this helps and if you have any other question regarding this.
I have a small problem with OrmLite on Android.
When I increment the database version, the onUpgrade method is called as expected in my OrmLite Helper. After the upgrade, the onCreate method is called and I get this exception:
11-24 10:09:45.720: ERROR/AndroidConnectionSource(390): connection saved
com.j256.ormlite.android.AndroidDatabaseConnection#44f0f478 is not the one
being cleared com.j256.ormlite.android.AndroidDatabaseConnection#44f5d310
I have no clue why the cleared connection is not the same as the saved one.
I've put also my database functions (insert...) into the OrmLite Helper class. Maybe this could be a problem?!?
A snippet from my helper class:
public class OrmLiteDBProvider extends OrmLiteSqliteOpenHelper
implements IEntityProvider, IDBProvider {
//snip
#Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(OrmLiteDBProvider.class.getName(), "Creating database and tables");
TableUtils.createTable(connectionSource, OrgManaged.class);
} catch (SQLException e) {
Log.e(OrmLiteDBProvider.class.getName(),
"Can't create database and tables", e);
throw new RuntimeException(e);
}
}
#Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource,
int oldVersion, int newVersion) {
try {
Log.i(OrmLiteDBProvider.class.getName(),
"Database version changed. Dropping database.");
TableUtils.dropTable(connectionSource, OrgManaged.class, true);
// after we drop the old databases, we create the new ones
onCreate(db);
} catch (SQLException e) {
Log.e(OrmLiteDBProvider.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
I think it's something simple I'm missing.
Thanks in advance for your effort.
Ok, I see the problem and it exists, unfortunately, in the sample program as well. In the ORMLite helper class, the onUpgrade method should use:
onCreate(db, connectionSource);
instead of the following which is calling the subclass:
onCreate(db);
I've reproduced this problem in the HelloAndroid example program which has been fixed. I've also fixed this properly in the OrmLiteSqliteOpenHelper base class in the Android side of the ORMLite code. Sorry for the problem.