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);
}
Related
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.
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);
}
I am trying to implement an Android application that uses SQLite as its data store. I am using ActiveAndroid. I have a model called Item, and I create items in the following way, calling this from the Activity's onCreate method:
Item item = new Item();
item.name = "test item";
item.save();
After launching my app, I then go to the Android Device Monitor to have access to the database files. And what I see are 2 databases in the filesystem of my app: Application.db and todoListDatabase:
Both of these databases contain a table called items, but only Application.db's version of the items table actually contains the new item records I created. Is that correct?
If this is correct, then what is the point of todoListDatabase?
Edit
Here are the relevant files I have:
My SQLite Helper class:
public class ItemDatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DATABASE_NAME = "todoListDatabase";
private static final String ITEMS = "items";
private static final String KEY_ID = "id";
private static final String KEY_BODY = "name";
public ItemDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_TODO_TABLE = "CREATE TABLE " + ITEMS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_BODY + " TEXT" + ")";
db.execSQL(CREATE_TODO_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion == 2) {
db.execSQL("DROP TABLE IF EXISTS " + ITEMS);
onCreate(db);
}
}
}
My Item class:
#Table (name = "Items")
public class Item extends Model {
#Column(name = "name")
public String name;
public Item() {
super();
}
public Item(String name){
super();
this.name = name;
}
}
There's just not enough information in this question, to allow it to be answered. SQLite Databases don't just appear. You have to create them. Typically, you do that with a SQLiteOpenHelper.
Unless you do something odd, your database will be in the directory:
/data/data/<your application's package name>/databases
For example, a database for the Google mail application might be:
/data/data/com.google.android.gm/databases/mail.db
Because I was using ActiveAndroid, creating a SQLiteOpenHelper was doing double work. That's why I was seeing 2 databases. To fix this, I deleted the ItemDatabaseHelper class. Then, when I go to the Android Device Monitor to see the database files, I see that Application.db is the only database there, and it has the items I created in it.
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;
}
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);
}