Android update row problems - java

In the app we are putting together I am trying to update rows from different Activities but it is throwing an error or not updating anything because I can't seem to get the current rowId once I move from one activity to the next. Any thoughts would be great.
This comes from the Activity:
Cursor value;
db.open();
long rowId = value.getLong(value.getColumnIndex("_id"));
boolean id = db.updateA(rowId, a1, a2, a3, a4);
db.close();
If I set the "rowId = 1" it updates that row just fine but I want to get the row that was just created in a different activity.
This is in the DBHelper file:
public boolean updateA(long rowId, String a1,String a2, String a3, String a4) {
ContentValues args = new ContentValues();
args.put(C_A1, a1);
args.put(KEY_A2, a2);
args.put(KEY_A3, a3);
args.put(KEY_A4, a4);
return db.update(TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
}

If you need to update the record I would suggest storing the record upon creation in a data object in memory and passing that to the other Activity that needs to do the update. The data object should have a property for its own ID, so you can just use that.
Not having a reference to the record you need to update will be a disaster. Also, if you know you always need to update the record, why don't you just do it on insert?

I don't get that.
You have an activity A that opena a DB, updates a row and closes the DB. This is done with the help of SQLiteOpenHelper class.
Now you move to activity B and now what? Post your primary key (you know it, you used it an A) with putExtra to B (or just put the whole row to B). If you put the rowid to B you can open, reread the row, update if needed and close again. If you just put the whole row to B, well that's all you need to do - but I wouldn't like that (e.g. what happens if B crashes?).
If you update in both activities without knowledge what both activities did (and without re-reading the rows) it's pure luck what you end with.

Try this:
return db.update(TABLE, args, KEY_ROWID + "='" + rowId + "'", null)

Related

Android - SQLite database not updating row

I have looked at the plethora of similar topics for the past couple days but none seem to help my actual situation or maybe it's just my inexperience.
I have a simple application that performs CRUD operations. I can successfully enter new rows into the table as well as delete them, however something is wrong with my update code and I can't find why. What has me puzzled is it worked once, then never did again regardless if I create new entries or delete the database entirely and start again. Isolating what I think the relevant code would be the operation flow is as follows.
The individual items are inside a RecyclerView and are sent from an inner class to the activity to be edited and updated:
public void onBindViewHolder(#NonNull ContactViewHolder holder, int position) {
final String contactName = mCursor.getString(mCursor.getColumnIndex(ContactEntry.COLUMN_NAME));
final int contactNumber = mCursor.getInt(mCursor.getColumnIndex(ContactEntry.COLUMN_PHONE_NUMBER));
final String contactMail = mCursor.getString(mCursor.getColumnIndex(ContactEntry.COLUMN_EMAIL));
final int currentPosition = position;
holder.mEditContact.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mContext, ContactUpdate.class);
intent.putExtra(CONTACT_POSITION, currentPosition);
intent.putExtra(EXTRA_NAME, contactName);
intent.putExtra(EXTRA_PHONE, contactNumber);
intent.putExtra(EXTRA_MAIL, contactMail);
mContext.startActivity(intent);
}
});
Then I get them in the retrieving class and organise the values into the appropriate EditText views. I'm sure there is a more efficient way but I'm still learning:
Intent intent = getIntent();
mPosition = intent.getIntExtra(ContactRecyclerAdapter.CONTACT_POSITION, 0);
mContactName = intent.getStringExtra(ContactRecyclerAdapter.EXTRA_NAME);
mContactPhone = intent.getIntExtra(ContactRecyclerAdapter.EXTRA_PHONE, 0);
mContactMail = intent.getStringExtra(ContactRecyclerAdapter.EXTRA_MAIL);
mUpdateName.setText(mContactName);
mUpdatePhone.setText("" + mContactPhone);
mUpdateMail.setText(mContactMail);
Lastly my method to update the row:
private void updateData() {
String name = mUpdateName.getText().toString();
String getPhone = mUpdatePhone.getText().toString();
int phone = Integer.parseInt(getPhone);
String mail = mUpdateMail.getText().toString();
SQLiteDatabase db = new ContactOpenHelper(this).getWritableDatabase();
ContentValues values = new ContentValues();
values.put(ContactEntry._ID, mPosition);
values.put(ContactEntry.COLUMN_NAME, name);
values.put(ContactEntry.COLUMN_PHONE_NUMBER, phone);
values.put(ContactEntry.COLUMN_EMAIL, mail);
String selection = ContactEntry._ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(mPosition)};
db.update(ContactEntry.TABLE_NAME, values, selection, selectionArgs);
db.close();
startActivity(new Intent(this, ContactList.class));
}
What is happening is the row is not being updated. Currently I have three mock entries entered. I put a break point at the update() line to try and find out what is happening. The original name for the this entry is "ted" and it's the third in the list. If I edit the EditText field and run the updateData() method, when the break point is hit it correctly shows the edited value as well the correct position of 2. However the database doesn't actually update. I am clearly misunderstanding how something works here.
To avoid bloat I have only included what I think is pertinent, but if anymore info is required then I'm happy to add.
Lastly here is a screen shot of the debugger at the break point showing what I perceive to be the correct information and where I'm completely confused as to why it is not working (I added a bunch of g's on the end of the name "ted" just to test if it would work).
Chnage your call to update as below
int count = db.update(ContactEntry.TABLE_NAME, values, selection, selectionArgs);
where count shows the number of the rows afftected with the update function, this would help you know exactly if there was any updated row or not.
Note :-We use like when, sometimes, you don’t know exactly the complete keyword that you want to query. For example, you may know that your most favorite song contains the word,elevator but you don’t know exactly the name.
If you know the exact value try to use:-
String selection = ContactEntry._ID + " =? ";
String selection = ContactEntry._ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(mPosition)};
Update this above code to this below code
String selection = ContactEntry._ID + " = ?";
String[] selectionArgs = { String.valueOf(mPosition)};
You want to update an exact row. But 'LIKE' keyword mostly uses for searches.
Besides, You are opening your activity when you update your data. Update or insert in database takes some time. When your next activity start, database may not finish its write operation. It could lead you to see the previous data. Make sure your database is updated and then update the view.
See your database from emulator that database has the new value or not. Then do the further work.
Try to delete you _Id from contentValues:
//values.put(ContactEntry._ID, mPosition);
I think you can't change PRIMARY_KEY, you say what line you want to update in:
String[] selectionArgs = { String.valueOf(mPosition)};
I have now solved this particular problem and the answer was quite simple and a little embarrassing. I was trying to use the cursor position for the row ID not realising that the database isn't using a zero-base index like the cursor, hence the primary key was not matching.
As I am using a RecyclerView I added the following line to my onBindViewHolder and passed the variable to my update activity which then could be used in the selectionArgs
final long id = mCursor.getLong(mCursor.getColumnIndex(ContactEntry._ID));

Not getting value correct value from sqlite table OR not inserting it properly

I have two sqlite tables in a specific database. I want to add the same data to both tables but on the second table I want to also store the ID of that entry in the first table.
What I do is add the entry ('Name', 'Description') to the first table then query to get the 'ID2' value then add the entry and the ID2 number into my second table after (Put ID2 in as ID3). I always rawquery to get my last entry's 'ID2' column value.
I have this working in the sense that it doesnt crash and does add a value to my second table BUT its isnt adding the value but instead some sort of reference which I do not understand so cant look up.
I would like a solution to get the the last 'ID2' value of my first table and insert it into my second table in 'ID3' column ALSO I would like an explanation of why what I have below is wrong.
Please reference my Java code below and screenshots of my two databases (the second showing the reference code not the value I want)
Thank you so much.
public boolean insetTheme(String name2,String Description){
SQLiteDatabase Mydb =this.getWritableDatabase();
ContentValues newThingAdd = new ContentValues();
newThingAdd.put(COL2_ALLTHEMES,name2);
newThingAdd.put(COL3_ALLTHEMES,Description);
long result = Mydb.insertOrThrow(TABLE_ALLTHEMES,null,newThingAdd);
Cursor res = Mydb.rawQuery("select * from "+TABLE_ALLTHEMES + " where 'ID2'" ,null);
//res.moveToLast();
if (res != null) {
res.move(-1);
}
ContentValues newThingAdd123 = new ContentValues();
newThingAdd123.put(COL2_CURRENTTHEMES,name2);
newThingAdd123.put(COL3_CURRENTTHEMES,Description);
newThingAdd123.put("ID3",res.toString());
long result2 = Mydb.insertOrThrow(TABLE_CURRENTTHEMES,null,newThingAdd123);
if ((result==-1)&(result2==-1))
return false;
else
return true;
}
First Table
Second Table
res is a Cursor so calling toString() on it won't give you what you want.
You need to use res.getString(0) or similar with the specific method based on what type the value is (String, int, boolean etc) and the number being the column number, for example, if the value you want is the third column that would be returned in the query, use res.getString(2) to get the value.
If I made a query like this:
Cursor cursor = Mydb.rawQuery("SELECT * FROM table_1");
and table_1 had 3 columns:
id, name, date
if I wanted the name, I would use
String name = cursor.getString(1);
Hopefully this is what you were after.

Android: column _id does not exist [duplicate]

I'm having trouble with something that works in the Notepad example.
Here's the code from the NotepadCodeLab/Notepadv1Solution:
String[] from = new String[] { NotesDbAdapter.KEY_TITLE };
int[] to = new int[] { R.id.text1 };
SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.notes_row, c, from, to);
This code seems to work fine. But just to be clear, I ran the ADB
utility and run SQLite 3. I inspected the schema as follows:
sqlite> .schema
CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE notes (_id integer primary key autoincrement, title text
not null, body text not null);
All seems good to me.
Now on to my application, which, as far as I can see, is basically the same with
a few minor changes. I've simplified and simplified my code, but the
problem persists.
String[] from = new String[] { "x" };
int[] to = new int[] { R.id.x };
SimpleCursorAdapter adapter = null;
try
{
adapter = new SimpleCursorAdapter(this, R.layout.circle_row, cursor, from, to);
}
catch (RuntimeException e)
{
Log.e("Circle", e.toString(), e);
}
When I run my application, I get a RuntimeException and the following prints
in LogCat from my Log.e() statement:
LogCat Message:
java.lang.IllegalArgumentException: column '_id' does not exist
So, back to SQLite 3 to see what's different about my schema:
sqlite> .schema
CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE circles (_id integer primary key autoincrement, sequence
integer, radius real, x real, y real);
I don't see how I'm missing the '_id'.
What have I done wrong?
One thing that's different between my application and the Notepad example is
that I started by creating my application from scratch using the
Eclipse wizard while the sample application comes already put together. Is
there some sort of environmental change I need to make for a new application
to use a SQLite database?
I see, the documentation for CursorAdapter states:
The Cursor must include a column named _id or this class will not
work.
The SimpleCursorAdapter is a derived class, so it appears this statement applies. However, the statement is technically wrong and somewhat misleading to a newbie. The result set for the cursor must contain _id, not the cursor itself.
I'm sure this is clear to a DBA because that sort of shorthand documentation is clear to them, but for those newbies, being incomplete in the statement causes confusion. Cursors are like iterators or pointers, they contain nothing but a mechanism for transversing the data, they contain no columns themselves.
The Loaders documentation contains an example where it can be seen that the _id is included in the projection parameter.
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
Contacts._ID,
Contacts.DISPLAY_NAME,
Contacts.CONTACT_STATUS,
Contacts.CONTACT_PRESENCE,
Contacts.PHOTO_ID,
Contacts.LOOKUP_KEY,
};
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// ...
return new CursorLoader(getActivity(), baseUri,
CONTACTS_SUMMARY_PROJECTION, select, null,
Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}
This has been answered and I would like to make it more comprehensive here.
SimpleCursorAdapter requires that the Cursor's result set must include a column named exactly "_id". Don't haste to change schema if you didn't define the "_id" column in your table.
SQLite automatically added an hidden column called "rowid" for every table. All you need to do is that just select rowid explicitly and alias it as '_id' Ex.
SQLiteDatabase db = mHelper.getReadableDatabase();
Cursor cur = db.rawQuery( "select rowid _id,* from your_table", null);
Tim Wu's code really works...
If you are using db.query, then it would be like this...
db.query(TABLE_USER, new String[] {
"rowid _id",
FIELD_USERNAME,
},
FIELD_USERNAME + "=" + name,
null,
null,
null,
null);
Yes , I also change the SELECT string query to fix this issue.
String query = "SELECT t.*,t.id as _id FROM table t ";
What solved my issue with this error was that I had not included the _id column in my DB query. Adding that solved my problem.
This probably isn't relevant anymore, but I just hit the same problem today. Turns out column names are case sensitive. I had an _ID column, but Android expects an _id column.
If you read the docs on sqlite, creating any column of type INTEGER PRIMARY KEY will internally alias the ROWID, so it isn't worth the trouble of adding an alias in every SELECT, deviating from any common utilities that might take advantage of something like an enum of columns defining the table.
http://www.sqlite.org/autoinc.html
It is also more straightforward to use this as the ROWID instead of the AUTOINCREMENT option which can cause _ID can deviate from the ROWID. By tying _ID to ROWID it means that the primary key is returned from insert/insertOrThrow; if you are writing a ContentProvider you can use this key in the returned Uri.
Another way of dealing with the lack of an _id column in the table is to write a subclass of CursorWrapper which adds an _id column if necessary.
This has the advantage of not requiring any changes to tables or queries.
I have written such a class, and if it's of any interest it can be found at https://github.com/cmgharris/WithIdCursorWrapper

How to use a get method for a SQLite Database management class in another class?

What I am trying to do is retrieve an ArrayList from another database manager class. Unfortunately all I can do because the manager class cannot work statically is create an instance in another class, then call the method. Then I got myself into passing that same instance into the method which asked for an SQLiteDatabase object. Now I've worked myself into a bind of confusion, when all I really want is to do is retrieve the arraylist to display a listview of elements from an SQL column.
EDIT: My post lacked clarity, so I'll try to specify exactly what is going wrong and what I am trying to accomplish here:
In a display (output) activity, I am trying to use a ListView to display elements contained in an SQL database. Currently, I am only focusing on one column (Assignment Names). My approach involved using a get method built into the database manager class, but because you cannot reference that method statically, I tried to use the method by creating an instance of that manager class. This would return an ArrayList of Inputted objects (each containing a name). It seemed to have worked, but when running the program, the LogCat protested that I was calling getDatabase recursively. After looking online, people recommended that I fix the issue by changing the method to ask for (SQLiteDatabase db) as parameters so the same database gets tossed around in the manager. Now I get confused here-- I'm not sure what to pass into this method from the display activity. It also doesn't help that from what I've heard from the comments, my get method doesn't traverse the SQL database properly. If you can solve this puzzle THANK YOU!
I'll post my code for diagnosis, hopefully an outside view will show exactly what's wrong with everything I'm trying here.
public Cursor getAssignmentNames(SQLiteDatabase db) {
return db.query(false, ASSIGNMENT_TABLE, COLUMN_TITLES,
" WHERE " + ASSIGNMENT_NAME + " ", null, null, null, " ORDER BY "+ASSIGNMENT_URGENCY_RATING, null);
}
/
public ArrayList<Inputted> getListOfAssignments (SQLiteDatabase db) {
Cursor names = getAssignmentNames(db);
ArrayList<Inputted> assList = new ArrayList<Inputted>();
names.moveToFirst();
while (!cursorsAreAfterLast(names) ) {
int go = 0;
assList.add(new Inputted(names.getString(go))
names.moveToNext();
go++;
}
return assList;
}
/
DBRecordsLayer assignmentRecords = new DBRecordsLayer(this,
"assignment.db", null, 1);
ArrayList<Inputted> assList = DBRecordsLayer.getListOfAssignments(assignmentRecords);
Your code is a bit confusing... In each iteration of the while loop, you are incrementing the cursor (names.moveToNext()); You are also incrementing go.
The result would be:
1st iteration: You are taking the data from the first column of the first query
2nd iteration: You are taking the data from the second column of the second query
etc...
I'm assume that you want to be reading data from the same column of the database for each iteration.
try this:
public ArrayList<Inputted> getListOfAssignments (SQLiteDatabase db) {
Cursor names = getAssignmentNames(db);
ArrayList<Inputted> assList = new ArrayList<Inputted>();
names.moveToFirst();
columnContainingStringToSendToInputtedConstructor = x; //replace the x with column you need from your table
while (!names.isAfterLast()) {
assList.add(new Inputted(names.getString(columnContainingStringToSendToInputtedConstructor));
names.moveToNext();
}
}

Android db.delete(); on ListActivity

I need help on a matter...
I created a listview with a cursord adapter that connects to my database,and shows me a list of everything that I saved in my table.
I later created a context menu that appears with longckick on the desired line
context position
id = getListAdapter().getItemId(info.position);
this is my method delete in the databaseHelper
void deleteReg(SQLiteDatabase db)
{
db.delete(TabellaRegistry.TABLE_NAME,null, null);
}
and i use that in my activity for delete the selected line:
final SQLiteDatabase db = databaseHelper.getWritableDatabase();
databaseHelper.deleteReg(db,null, null, null, null, null, null);
but doing so...i delete all in my table...
how do I delete only the selected line via the context menu?
I hope I explained myself, thanks in advance
By passing NULL as your second argument on this line:
db.delete(TabellaRegistry.TABLE_NAME,null, null);
You will always be deleting the whole table. As mentioned in the Android documentation, the parameters are as following:
public int delete (String table, String whereClause, String[] whereArgs)
table - the table to delete from
whereClause - the optional WHERE clause to apply when deleting.
Passing null will delete all rows.
So let's say you want to delete the line where BOOK_ID is 6 you would have something like:
public boolean deleteTitle(String id)
{
return db.delete(DATABASE_TABLE, BOOK_ID + "=" + id, null) > 0;
}
SQLite Class Overview: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
In order to delete specific rows, you need to put a where clause in the delete statement delete
If you check the api docs for this method you can get the answer yourself.
public int delete (String table, String whereClause, String[] whereArgs)
Parameters
table the table to delete from
whereClause the optional WHERE clause to apply when deleting. Passing null will delete all rows.
You are passing null in where clause which is the cause of deleting all records.

Categories