I need to delete a record from ORMLite Database I can delete a record by id using as below
#Override
public void Delete(int id) throws SQLException {
this.dao.deleteById(id);
}
but what if I have to delete a record from same table not by id but by name or any other field
I want something like
public void Deletefromcanteen(String name,MealType mealtype) {
this.dao.deletebyName(name);
}
what query should i write using querybuilder to delete a record where name = name and mealtype = say (lunch)
I tried something like this in my databasehelper class
public void deletefromcanteen(int id, String mealtype) {
try {
Dao<CanteenLog, Integer> canteenDao = getCanteen();
DeleteBuilder<CanteenLog, Integer> deleteBuilder = canteenDao
.deleteBuilder();
deleteBuilder.where().eq("user_id", id).and().eq("meal", mealtype);
canteenDao.delete(deleteBuilder.prepare());
} catch (Exception e) {
...
}
}
deleteBuilder.where().eq("FIELD_NAME", arg);
deleteBuilder.delete();
Update:
For example :
//Get helper
DatabaseHelper helper = OpenHelperManager.getHelper(App.getContext(), DatabaseHelper.class);
//get dao
Dao dao = helper.getDao(YOUR_CLASS.class);
//delete elements from table in field by arg
DeleteBuilder<CanteenLog, Integer> deleteBuilder = dao.deleteBuilder();
deleteBuilder.where().eq("FIELD_NAME", arg);
deleteBuilder.delete();
Good luck!
To save building a query, you can do a select to find the ID, then do a delete by ID. Thsi will be straightforward if you already have the select query set up for this table.
It can be done also like that
DatabaseHelper.getInstance().getDao(YourObject.class).delete(yourObjectInstance);
If you are using Kotlin, you will need to do something like this instead since the type inference is not currently working correctly for the fluent syntax:
val deleteBuilder = dao.deleteBuilder()
val where = deleteBuilder.where().eq("address", address)
deleteBuilder.setWhere(where)
deleteBuilder.delete()
If you already have an instance of the object (or object list) you want to delete, just do :
//Get helper
DatabaseHelper helper =
OpenHelperManager.getHelper(App.getContext(), DatabaseHelper.class);
// delete 'em !
helper.getDao(YourObject.class).delete(yourObjectInstance);
If you don't have the instance to delete or you want to do it SQL way(!):
//Get helper
DatabaseHelper helper =
OpenHelperManager.getHelper(App.getContext(), DatabaseHelper.class);
//get dao
Dao dao = helper.getDao(YOUR_CLASS.class);
//delete elements from table in field by arg
DeleteBuilder<CanteenLog, Integer> deleteBuilder = dao.deleteBuilder();
deleteBuilder.where().eq("FIELD_NAME", "FIELD_VALUE");
deleteBuilder.delete();
If you need a more complicated Where logic, then use deleteBuilder.where().or() or deleteBuilder.where().and() to add more constraints.
Related
I'm trying to test Room DB after including a new Column date. But I'm not getting how to insert data as I cannot use context in Testing.java file.
my code looks like this,
#RunWith(AndroidJUnit4.class)
public class MigrationTest {
private static final String TEST_DB = "note_database";
#Rule
public MigrationTestHelper helper;
public MigrationTest() {
helper = new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
NoteDatabase.class.getCanonicalName(),
new FrameworkSQLiteOpenHelperFactory());
}
#Test
public void migrateAll() throws IOException {
// Create earliest version of the database.
SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 2);
db.execSQL("INSERT INTO note_table (title,description,priority,date)" +
" VALUES ('title_test','description_test','priority_test','10/12/2019'); ");
db.close();
// Open latest version of the database. Room will validate the schema
// once all migrations execute.
NoteDatabase appDb = Room.databaseBuilder(
InstrumentationRegistry.getInstrumentation().getTargetContext(),
NoteDatabase.class,
TEST_DB)
.addMigrations(ALL_MIGRATIONS).build();
appDb.getOpenHelper().getWritableDatabase();
appDb.close();
}
// Array of all migrations
private static final Migration[] ALL_MIGRATIONS = new Migration[]{
MIGRATION_1_2};
}
This code was working fine but , look at this reference code. i need to do something like this.
and I'm not getting how to read getMigratedRoomDatabase data. can anyone help me on this.
// MigrationTestHelper automatically verifies the schema
//changes, but not the data validity
// Validate that the data was migrated properly.
User dbUser = getMigratedRoomDatabase().userDao().getUser();
assertEquals(dbUser.getId(), USER.getId());
assertEquals(dbUser.getUserName(), USER.getUserName());
// The date was missing in version 2, so it should be null in
//version 3
assertEquals(dbUser.getDate(), null);
That is nothing but appDb in your code. it will look like
appDb.userDao().getUser();
We try to update sqlite_sequence with the following code.
WeNoteRoomDatabase weNoteRoomDatabase = WeNoteRoomDatabase.instance();
weNoteRoomDatabase.query(new SimpleSQLiteQuery("UPDATE sqlite_sequence SET seq = 0 WHERE name = 'attachment'"));
However, it has no effect at all. I exam the sqlite_sequence table content using SQLite browser. The counter is not reset to 0.
If we try to run the same query manually using SQLite browser on same SQLite file, it works just fine.
Our Room database is pretty straightforward.
#Database(
entities = {Attachment.class},
version = 6
)
public abstract class WeNoteRoomDatabase extends RoomDatabase {
private volatile static WeNoteRoomDatabase INSTANCE;
private static final String NAME = "wenote";
public abstract AttachmentDao attachmentDao();
public static WeNoteRoomDatabase instance() {
if (INSTANCE == null) {
synchronized (WeNoteRoomDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
WeNoteApplication.instance(),
WeNoteRoomDatabase.class,
NAME
)
.build();
}
}
}
return INSTANCE;
}
}
Any idea what we had missed out?
Additional information : clearing sqlite_sequence is not working in android room
Room doesn't use SQLiteDatabase - but it uses SupportSQLiteDatabase, while it's source code states, that it delegates all calls to an implementation of {#link SQLiteDatabase}... I could even dig further - but I'm convinced, that this is a consistency feature and not a bug.
SQLiteDatabase.execSQL() still works fine, but with SupportSQLiteDatabase.execSQL() the same UPDATE or DELETE queries against internal tables have no effect and do not throw errors.
my MaintenanceHelper is available on GitHub. it is important that one initially lets Room create the database - then one can manipulate the internal tables with SQLiteDatabase.execSQL(). while researching I've came across annotation #SkipQueryVerification, which could possibly permit UPDATE or DELETE on table sqlite_sequence; I've only managed to perform a SELECT with Dao... which in general all hints for the internal tables are being treated as read-only, from the perspective of the publicly available API; all manipulation attempts are being silently ignored.
i think query is wrong, you should try below query
weNoteRoomDatabase.query(new SimpleSQLiteQuery("UPDATE sqlite_sequence SET seq = 0 WHERE name = attachment"));
I'm using room database version 2.2.5
Here I'm unable to execute this query using Room Dao structure, so make one simple class and access method as like this and I got successful outcomes so this one is tested result. I'm using RxJava and RxAndroid for same.
public class SqlHelper {
private static SqlHelper helper = null;
public static SqlHelper getInstance() {
if (helper == null) {
helper = new SqlHelper();
}
return helper;
}
public Completable resetSequence(Context context) {
return Completable.create(emitter -> {
try {
AppDatabase.getDatabase(context)
.getOpenHelper()
.getWritableDatabase()
.execSQL("DELETE FROM sqlite_sequence WHERE name='<YOUR_TABLE_NAME>'");
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
});
}
}
Execute:
SqlHelper.getInstance()
.resetQuizSequence(context)
.subscribeOn(Schedulers.io()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> {}, error -> {});
Table sql_sequence is not managed by Room, so you need to edit it using a SupportSQLiteDatabase.
Try this:
String sqlQuery = "DELETE FROM sqlite_sequence WHERE name='attachment'";
weNoteRoomDatabase().getOpenHelper().getWritableDatabase().execSQL(sqlQuery);
This works for me - Room 2.2.6
String sqlQuery = "DELETE FROM sqlite_sequence WHERE name='attachment'";
<YourDatabase>.getInstance(mContext).getOpenHelper().getWritableDatabase().execSQL(sqlQuery);
I'm creating my first data enabled app but am struggling with the last part - actually adding and retrieving the data. For now I am only concerned with adding data to the table. Following this tutorial I have created model classes for my tables and a DBHelper class with all my CRUD methods (I can post all these if required but not sure they are necessary to answer this question. Please correct me if I am wrong!). Unfortunately the tutorial ends here and doesn't go into detail on how to pass the data from the UI of the app into the DB.
After some Google searches I have found an example of how to pass some data to these methods but only how to pass one piece of data at a time, so only really useful if my table has just one field - mine has more than one.
For example, if I have a a table for "Todo" tasks, in my dbhelper my create method may be;
public void createTodo(String todoText) {
ContentValues contentValues = new ContentValues();
contentValues.put("todo", todoText);
// Insert into DB
db.insert("todos", null, contentValues);
}
so from my activity I just need
dao.createTodo(todoTextValue);
For my app I will be adding more than one field at a time, so my create method looks like this;
public long createSite(Site site){
SQLiteDatabase database = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_SITE_NAME, site.getSiteName());
values.put(KEY_SITE_LAT, site.getSiteLat());
values.put(KEY_SITE_LON, site.getSiteLon());
values.put(KEY_CREATED_AT, site.getSiteCreatedDateTime());
// Insert Row
long siteid = database.insert(TABLE_SITES, null, values);
So my question really is how I can pass all the different bits of data to the createSite method.
I don't know if this really needs an answer, but well here's a code...
Assuming your Site class is like this.
public class Site {
private String siteName;
private double siteLat;
private double siteLon;
private Date siteCreatedDateTime;
// getters and setters here
}
You then pass the data from your EditText value to your new Site object. It will look like this in your activity.
EditText siteNameInput = (EditText) findViewById(R.id.siteNameInput);
EditText siteLatInput = (EditText) findViewById(R.id.siteLatInput);
EditText siteLonInput = (EditText) findViewById(R.id.siteLonInput);
EditText siteCreatedDateTimeInput = (EditText) findViewById(R.id.siteCreatedDateTimeInput);
String siteName = siteNameInput.getText().toString();
String siteLat = siteLatInput.getText().toString();
String siteLon = siteLonInput.getText().toString();
String siteCreatedDateTime= siteCreatedDateTimeInput.getText().toString();
Site site = new Site();
site.setSiteName(siteName);
site.setSiteLat(siteLat);
site.setSiteLon(siteLon);
site.setSiteCreatedDateTime(siteCreatedDateTime);
dao.createSite(site);
Hope this helps you... You can learn more on Object-Oriented programming in Java here
public long createSite(Model site,String name, String address){
SQLiteDatabase database = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, site.name);
values.put(KEY_ADDRESS, site.address);
// Insert Row
long siteid = database.insert(TABLE_SITES, null, values);
to add elements to the class you just add
public class Model {
String name;
String address;
//add year as many as you need
Model(String name, String address){
this.name=name;
this.address=address;
}
}
And in you activity you call this
In java to add a new object in this case Model
Model x = new Model("josh","Ireland");
and you just pass to
dao.createTodo(x);
Todo and Site are models. Each variable represents a column of that table. You need to create a custom model for each of your tables. The createSite method takes an object of type Site and adds it as a row in the TABLE_SITES in the DB. values.put(...)takes columnName, value. So here you give your own column names and values.
Instead of getting into all this I suggest you use an orm like active android:
http://www.activeandroid.com/
I have a problem with making request using these both libraries. I wanted to get all queries from my table Table_events with .queryforall() but then I saw this thread and tried to make query with rawQuery but it offers only queryRaw(). The request looks like this:
private Dao<Table_Events, Integer> tEventDao;
public DAOManager(final DatabaseHelper databaseHelper)
{
this.tEventDao= GettEventDAO(databaseHelper);
}
public String[] Getall()
{
GenericRawResults<String[]> rawResults = null;
try
{
rawResults = tEventDao.queryRaw("select * from tableEvents");
}
catch (SQLException e)
{
e.printStackTrace();
}
return resultArray;
}
any ideas how make a query?
Your GettEventDAO function is returning an object that conforms to the Dao interface of ORMLite. You would need to make sure the implementation of ORMLite is able to interface with SQLCipher for Android which would typically return a Cursor representing the resultset of your query.
I've executed some queries on my SQLite DB on Android.
Main instruction used is this:
Cursor cursor = myDB.rawQuery(select, null);
Now I want the results of this query to be converted to a generic class I've created in the project. If you think I want an ORM system, you are right, but all I've found now are ORM systems that want to query the DB, save objects in the DB and manage the DB itself.
Instead now I need a 'simple' ORM feature that can do exactly what the google.gson library does with JSON strings, it converts JSON strings to custom objects, and I want the same but for converting SQLite cursors to my Classes.
Any suggestion how to do this?
I don't think there is an automated way to do this. Just populate the object yourself. For example, if your cursor was just an id and a name and you wanted to create a Person object:
Person populatePerson(Cursor cursor)
{
try
{
int idIndex = cursor.getColumnIndexOrThrow("_id");
int nameIndex = cursor.getColumnIndexOrThrow("name");
long id = cursor.getLong(idIndex);
String name = cursor.getString(nameIndex);
return new Person(id, name);
}
catch (Exception e)
{
e.printStackTrace();
}
}
You could wrap this function in your own Cursor class to make the process transparent.
Check out MicroOrm
private static class SomeObject {
#Column(SOME_FIELD)
private String mSomeField;
}
SomeObject object = microOrm.fromCursor(cursor, SomeObject.class);