I have started migrating my SQLite code to the room. I want to know how can we create insertOrThrow (as in SQLite) method in DAO?
Declare your DAO's method with throws SQLException (android.database.SQLException).
Hope this work for you as in my case.
#Insert
public abstract void guardaVariedades(Variedad... variedades) throws SQLException;
if you are having problem when insert a new row (due to conflicts when adding, ie: the value you add already existed), you can try adding one of the following attribute to Insert annotation:
ABORT: (default)to roll back the transaction on conflict
REPLACE: to replace the existing rows with the new rows
IGNORE: to keep the existing rows
I have searched ways to throw the exception but didn't succeed, the above way solve the problem
Related
how do I VACUUM my RoomDatabase for my Application?
I build my entire Application around Room and at a certain point one big table gets deleted reguarly and later filled again.
I tried to create an additional DAO-Interface with the Query:
#Dao
public interface GenericDao {
#Query("VACUUM")
void vacuum();
}
but I get the Error:
Error:(13, 10) error: UNKNOWN query type is not supported yet. You can use:SELECT, UPDATE, DELETE
Is there a workaround?
Basically what I need is, that once my Table gets completely emptied, Autoincrement starts at 1 again.
I'm fairly new to Database Design, so please be understanding if this is against best Practice.
And yes: I exhausted Google and every other Platform I know.
Many Thanks in advance!
Dao can look as follows :
#Dao
public interface RawDao {
#RawQuery
int vacuumDb(SupportSQLiteQuery supportSQLiteQuery);
}
Run the query like this :
rawDao.vacuumDb(new SimpleSQLiteQuery("VACUUM"));
Is there a workaround?
Call getOpenHelper() on your RoomDatabase subclass, to get a SupportSQLiteOpenHelper. Call getWritableDatabase() on it to get a SupportSQLiteDatabase. Then, since I don't think that VACUUM returns a result set, call execSQL("VACUUM") on the SupportSQLiteDatabase.
Basically what I need is, that once my Table gets completely emptied, Autoincrement starts at 1 again.
IMHO, you should not be making any assumptions about how autoincrement fields get incremented.
Since the update to greenDao 3, statements like those do not work anymore:
getDatabase().insert(TABLENAME, null, values);
getDatabase().delete(...);
getDatabase().update(...);
The getDatabase() is a greenDao interface which doesn't have insert, delete and update methods. Thus, it gives me compile time errors. Anybody solved the issue?
The class you are getting back is org.greenrobot.greendao.database.Database, which is a database abstraction meant only for greenDAO. You have two options:
You hold the reference to the original SQLiteDatabase and pass it to greenDAO during initialization.
The Database abstraction class has a method getRawDatabase, which returns the underlying SQLiteDatabase. If you are not using encryption, it will be always android.database.sqlite.SQLiteDatabase. You have to do a cast.
I tried update(Object), update(PreparedUpdate), executeRaw(String), updateRaw(String), and even tried directly using the helper class then using getData(String query). But my table's foreign field is still not updated. Any thoughts why this is happening?
I found out that I am using the method update(Object) on other methods while passing an outdated instance of the object I am trying to update. So once I use the actual update(PreparedUpdate) method, I am reverting the object back to its original state as some other method is using update(outdated Object)
I'm using GreenDao and creating a core function that help you to update some values of an entity, and if the entity is not in the database then it also inserting it. The problem is that I'm always getting the cached copy of the entity, I know that GreenDao manage some simple cache and I would like to have the ability bypass it. does anyone knows how I can query right from the database?
This doesn't work
.Dao().queryBuilder().where(comDao.Properties.Id.eq(id)).build().listLazyUncached();
GreenDao indeed has Inner caching mechanism in its daoCore.jar sources.
You can disable the caching easily by searching for the code that put() and get() entities from the cache.
which is a: HashMap<? extends AbstractDao>.
Then generate MyDaoCore.jar and add it to your project.
Secondly, in order to update or insert and entity (without replacing it entirely) you need to implement the following pseudo code. I'm sorry that I'm not adding the actual code, I solved it long time ago.
public void insertOrUpdate(List<? extends AbstractDao> entities){
List<Entity> toInsert;
List<Entity> toUpdate;
for (Entity e : entities)
{
if( e.inDatabase() )
toUpdate.add(e);
else
toInsert.add(e);
}
Dao.updateAll(toUpdate);
Dao.insertAll(toInsert);
}
Edit 1:
You can use IN statement in order to get all the ids of an entity in only one query like this:
.where(Dao.Properties.Id.in(ids)).build().list();
When referring to database tables I usually use syntax like this: my_database_name.my_table_name
I am trying to do the same in Android but am having trouble understanding how to name a database.
Would you just execute this SQL as you would in the Sqlite3 client? i.e.
ATTACH "my_database_file" AS my_database_name;
Here is what I tried in my onCreate method:
db.execSQL("Attach 'hq_db' AS hq_db;");
but I'm getting this error:
04-05 11:13:35.676: ERROR/AndroidRuntime(860): Caused by: android.database.sqlite.SQLiteException: cannot ATTACH database within transaction: Attach 'hq_db' AS hq_db;
How do I execute SQL statements on Android outside of a transaction to make this work?
Edit: It might also have something to so with the superclass constuctor, though the super class constructor string sets the file name (which is working properly) and it seems nothing else:
private class databaseOpenHelper extends SQLiteOpenHelper {
public q_player_databaseOpenHelper() {
super(MyApp.getContext(), "my_db_file", null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("Attach 'my_db_file' AS my_db_name;");
db.execSQL("PRAGMA foreign_keys=ON;");
}
Note: I have stripped this code down so it would fit my problem
You need to call db.execSQL("ATTACH 'hq_db' AS hq_db;"); before you start any kind of transaction. Do the attachment first, and then start the transaction.
Are you calling beginTransaction or executing SQL which begins a transaction before trying to attach your other database?
You're probably creating the database with AutoCommit=0. This puts you in a transaction so that it doesn't need to write to the database file after every INSERT. But it also means you can't ATTACH to another database. Create the DB, set AutoCommit=1, ATTACH, then set AutoCommit=0.