before voting down please read my question , which I have searched a lot but I couldn't find the answer yet, so I would appreciate if you give me hand to overcome the problem.
Actually I need to update a tuple in a table named "Demographics". But it seems my code does not work correctly, and in fact after running the app , I got the result "0" for updating which means nothing get updated.
12-21 12:34:54.190 2351-2367/? D/Update Result:: =0
I guess my problem is due to not pointing to the right row of the table based on Primary key. Actually when a user Register to my app the following things should happen:
1- Create a tuple in "Demographics" table --> username, password and email will be inserted. An auto increment primary key also constructed and inserted.
2- user logins , then he can complete rest of information in "Demographics" table. --> this MODIFICATION is the "update" process which I', asking.
Would you please tell me if the following codes are wrong or have any implicit error?
DemographicsCRUD.java
public long UpdateDemographics(Demographics_to demoId) {
//SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(DataBaseHelper.lastName, demoId.getD_lastName());
values.put(DataBaseHelper.firstName, demoId.getD_firstName());
values.put(DataBaseHelper.dateOfBirth, demoId.getD_dateOfBirth())
long result = database.update(dbHelper.Demographics_Table, values,
WHERE_ID_EQUALS,
new String[]{String.valueOf(demoId.getD_patientID())});
Log.d("Update Result:", "=" + result);
// db.close();
return result;
}
here is where I call the above code:
private void updateDemographicsTable()
{
ep_demoId = new Demographics_to();
String ep_na = ep_name.getText().toString();
String ep_fa = ep_family.getText().toString();
.
.
.
ep_demoId.setD_dateOfBirth(ep_bd);
ep_demoId.setD_firstName(ep_na);
ep_demoId.setD_lastName(ep_fa);
}
#Override
protected Long doInBackground(Void... arg0) {
long result = ep_demoCRUD.UpdateDemographics(ep_demoId);
return result;
}
#Override
protected void onPostExecute(Long result) {
if (activityWeakRef.get() != null
&& !activityWeakRef.get().isFinishing()) {
if (result != -1)
Toast.makeText(activityWeakRef.get(), "Information Updated!",
Toast.LENGTH_LONG).show();
}}
Looks like whatever you are passing in as the patientID does not have a matching record in the database or the dataobject "Demographics_to" has the patient ID set incorrectly.
Related
I have an android program that passes 2 value to mySQL, that is Time in and Time out. I don`t know what happen but I have a scenario that the data passed is incomplete. For example i will create a record and the only need to put is time in after i type the time i will click save so the record is time in has a data and time out is null. After saving, my auto passer sends that data to mySQL. The next thing I will do is to edit that record to add Time Out so both of them has a data. auto passer will run after checking to my database my both of columns has a data. Now this is where the error begins, I have a button call refresh which will retrieve my data from mySQL,create a JSON of that then send it in my android after the process the returned data has no Time Out and when i check it the data in mySQL has no time out also even i add it. I dont know what happened
What I did in my Java is to create a JSONArray the convert it to string the pass it in my php file then my php file decodes it then loop it while saving to database.
This is how i create a json
JSONArray vis_array = new JSONArray();
Cursor unsync_vis = Sync.Unsync_Visit_All();
while (unsync_vis.moveToNext()) {
JSONObject vis_data = new JSONObject();
try {
vis_data.put("t1", formatInsert_n(unsync_vis.getString(unsync_vis.getColumnIndex("t1"))));
vis_data.put("t2", formatInsert_n(unsync_vis.getString(unsync_vis.getColumnIndex("t2"))));
vis_array.put(vis_data);
} catch (JSONException e) {
e.printStackTrace();
Log.e("Auto Sync Error", e.getMessage());
}
}
public String formatInsert_n(String data) {
if (TextUtils.isEmpty(data) || data.length() == 0) {
data = "null";
} else {
data = data.replace("'", "''");
data = data.replace("null", "");
if (data.toString().matches("")) {
data = "null";
} else {
data = "'" + data + "'";
}
}
return data;
}
after creating that json, i will convert it to string the pass it using stringRequest then in my php i will decode it use for loop the save it in mySQL
Here is the php code
<?php
header('Content-Type: application/json');
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$insert_visit_new = isset($_POST['insert_visit_new']) ? $_POST['insert_visit_new'] : "";
if ($insert_visit_new != "") {
$vis_array = json_decode($insert_visit_new, true);
$vis_count = count($vis_array);
for ($i = 0; $i < $vis_count; $i++) {
$vis = $vis_array[$i];
$t1 = $vis['t1'];
$t2 = $vis['t2'];
$ins_sql = "INSERT INTO table t1,t2 VALUES ('$t1','$t2') ON DUPLICATE KEY UPDATE t1 = $t1,t2 = $t2"
$stmt = $DB->prepare($ins_sql);
$stmt->execute();
}
}
echo "done";
?>
by the way the code above is inside an AsyncTask and the class is a BroadcastReceiver
is the cause is i dont unregister my BroadcastReceiver?
or my jsonArray name from this class and inside my refresh button are same?
my question is whats wrong? looks like it still passes the old data. any help is appreciated TYSM
I'm using this code to actually let the user send a questionand 4 answers (it's a long story), and storage it on my game database. This is the code I used, after seeing the docs and just the table doesn't get updated. I don't really know why
private void sendQuestion() {
ParseUser currentUser = ParseUser.getCurrentUser();
String role = currentUser.get("Role").toString();
if(role.equals("Founder"))
{
String questionText = mQuestion.getText().toString();
String[] answers = new String[4];
for(int i = 0; i < 4; i++) {
answers[i] = mAnswers[i].getText().toString();
}
ParseObject question = new ParseObject("Questions");
question.put("lang", mSelectedLang);
question.put("question", questionText);
for(int i = 0; i < 4; i++) question.put("answer" + (i+1), answers[i]);
question.put("enabled", true);
question.put("from", currentUser);
question.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
Log.d("MyApp", "Done");
}
});
}else
Log.d("MyApp", "Not founder");
}
This is what I get from the Logs
05-27 19:57:21.063 2307-2307/*************** D/MyApp﹕ Send question button pressed
05-27 19:57:21.530 2307-2307/*************** D/MyApp﹕ Done
Says it's done but the Table Questions is not updated, as said. Pay attention that both "lang" and "from" are relations fields, so I put there object and not simple values like Strings or Integer.
Why doesn't the table get updated?
Here you can look the official docs to save an object https://www.parse.com/docs/android/guide#objects-saving-objects
I self resolved changing the rows type from 'Relation' to 'Pointer', as I read here https://parse.com/questions/expected-relation_user-but-got-_user (didn't find it because it was asked for iOS but it's not about the wrong code).
Now it works.
I think you should change
question.put("from", currentUser);
with something like:
question.put("from", currentUser.getId()); // pass id of user, not object itself
I am using a content provider to read/write from a database that allows a user to organize prescriptions. Currently, I am implementing a DialogFragment that allows the user to enter a new medication. The dialog contains two EditTexts, one for strength, and one for medication name.
The table is designed so that (name, strength) is a unique key. Here is my insert method:
public Uri insert(Uri uri, ContentValues values) {
final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
final int match = sUriMatcher.match(uri);
long _id; // Value used for inserts.
Uri returnUri;
switch(match){
case MEDICATION:
_id = db.insert(PMContract.MedicationEntry.TABLE_NAME, null, values);
if(_id > 0)
returnUri = PMContract.MedicationEntry.buildMedicationUri(_id);
else
throw new UnsupportedOperationException("Failed to insert row into: " + uri);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
As you can guess, if the user inputs a name and strength that already exist, an SQLiteConstraintException occurs. However, all I do here is throw an UnsupportedOperationException, something that I learned from a tutorial on content providers.
What I would like to do, is handle the situation specifically where a duplicate key is entered, so I can relay that information to the user (likely via a Toast).
I have tried adding a try/catch to where I make the insert call:
try{
getActivity().getContentResolver().insert(PMContract.MedicationEntry.CONTENT_URI, values);
} catch(SQLiteConstraintException e){
}
But SQLiteConstraintException is not the one that is caught, but instead an UnsupportedOperationException.
How can I adjust the ContentProvider code so that I know when I have a ConstraintException, and treat everything else as an UnsupportedOperationException?
EDIT
I have tried to wrap a try/catch block around the db.insert call:
case MEDICATION:
try {
_id = db.insert(PMContract.MedicationEntry.TABLE_NAME, null, values);
} catch(SQLiteConstraintException e){
String s = e.getMessage();
} catch(Exception e1){
String s1 = e1.getMessage();
}
if(_id > 0)
returnUri = PMContract.MedicationEntry.buildMedicationUri(_id);
else
throw new UnsupportedOperationException("Failed to insert row into: " + uri);
break;
And I used the debugger to see the exception that was being thrown by db.insert(). However, the debugger didn't hit a breakpoint in either of the catch blocks, even though the error text was printed in the logcat. I'm not sure why an exception is printed to the logcat but the debugger doesn't hit those breakpoints.
Instead of throwing an exception, return null as your Uri - then you can check the result of the insert() call - if you get a null return value, you know it was a constraint issue.
After trying Ian's suggestion and editing my question, I realized I was having the same problem as this question.
Changing the line of code to db.insertOrThrow() caused the ConstraintException to be thrown if it happened, and I was able to catch that in the DialogFragment:
// In the ContentProvider
_id = db.insertOrThrow(PMContract.MedicationEntry.TABLE_NAME, null, values);
// In the Dialog Fragment
try{
getActivity().getContentResolver().insert(PMContract.MedicationEntry.CONTENT_URI, values);
dismiss();
} catch(SQLiteConstraintException e){
Toast.makeText(getActivity(), "A medication with this name and strength already exists.", Toast.LENGTH_SHORT).show();
} catch(UnsupportedOperationException uoe){
Toast.makeText(getActivity(), "Unable to insert new medication.", Toast.LENGTH_SHORT).show();
}
in my app searchbar is there, wheren in user types the text. Whenever a text get changes in the filed i will call a query to DB to get the related search items. But sometimes it crashes.
Here is the code i'm doing to call DB
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
if(newText.trim().equals(""))
{
return false;
}
//showSearchSuggestions(newText);
mfilterdata = mController.get_controllerObj().getDBManager().getAllSuggestedFilter(newText);
if(mSearchadapter != null)
mSearchadapter.swapCursor(mfilterdata);
return false;
}
Here is how i m querying in DB manager
public Cursor getAllSuggestedFilter(String filterString)
{
String READ_QUERY = "SELECT * FROM " + Tbl_ITEM_TABLE + " where "+
item.TITLE + " Like" + "\"%" + filterString + "%"+"\"";
if(mcursorForFilter != null)
{
mcursorForFilter.close();
mcursorForFilter = null;
}
try
{
mcursorForFilter = getReadableDatabase().rawQuery(READ_QUERY, null);
}
catch(Exception ee)
{
}
return mcursorForFilter;
}
randomly i get exception like
java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT * FROM itemtable where title Like"%t%")
That's probably because you are closing the cursor in the wrong place, and trying to use it after that, but you cannot use an already closed cursor.
I would get rid of this part of the code:
if(mcursorForFilter != null) {
mcursorForFilter.close();
mcursorForFilter = null;
}
Instead, close the old cursor after you set the new one. swapCursor() returns the old Cursor, or returns null if there was not a cursor set, also returns null if the if you try to swap the same instance of the previously set cursor. Knowing that, you can try something like this:
Cursor c = mSearchadapter.swapCursor(mfilterdata);
if(c != null)
c.close();
Try that, and let me know if that helped.
Note that when you are using a Loader (LoaderManager.LoaderCallbacks), the framework is going to close the old cursor. This is what the documentation says:
onLoadFinished:
The loader will release the data once it knows the application is no
longer using it. For example, if the data is a cursor from a
CursorLoader, you should not call close() on it yourself. ...
I have 7,464 siteID Integers stored in a List with the same name (siteID). I am looping through the List and using each siteID Integer to query an SQL table with JPA to return a SiteTable instance and get its postcode String.
I am then using those postcode Strings to check XML files to retrieve latitude and longitude values against each postcode. Below is the loop;
for (Integer id : siteID){
siteTable = em.find(SiteTable.class, id);
XMLPositionRetriever.runXMLQuery(siteTable.getPostcode());
}
That postcode String is then put into the runXMLQuery(String toFind) method in the class below;
public class XMLPositionRetriever extends DefaultHandler{
String postcodeToFind;
boolean found = false;
public XMLPositionRetriever(){
}
public XMLPositionRetriever(String toFind){
postcodeToFind = toFind;
}
public static void runXMLQuery(String toFind){
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
XMLPositionRetriever handler = new XMLPositionRetriever(toFind);
saxParser.parse("src\\haldata\\postcodes"+toFind.charAt(0)+".xml", handler);
}
catch(Exception e){
System.out.println(e);
}
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (postcodeToFind.equals(attributes.getValue("postcode"))){
System.out.println("The postcode '"+postcodeToFind+"', has a latitude of "+attributes.getValue("latitude")+" and a longitude of "+attributes.getValue("longitude"));
found = true;
}
}
#Override
public void endDocument(){
if(!found){
System.out.println("Not Found");
}
}
}
The event handlers above make sure that something is always outputted even if the postcode is not found in any of the XML files, or even if there is an exception. So, what I would expect is for the code above to println 7464 times, but instead I am getting 50 or so lines outputted. It appears that the loop isn't actually running for each siteID, but the code says it should be. I've narrowed the problem down to the code I've shown above (most likely within the loop itself) but now I can't see anything wrong. Any suggestions?
The XMLs look like this, but with up to 300,000 entry elements;
<?xml version="1.0"?>
<postcodes>
<entry postcode='AB1 0AA' latitude='7.101478' longitude='2.242852' />
</postcodes>
Sorry to dump so much code on you all, but I don't think I could give you a complete picture with less.
The problem occurs (below, commented);
for (Integer id : siteID){
siteTable = em.find(SiteTable.class, id);
XMLPositionRetriever.runXMLQuery(siteTable.getPostcode());// <--- Null point exception on this line.
}
Where em.find() did not find an Entity class, it returned null. In such cases siteTable.getPostcode() was throwing the NullPointerException. So, I added in an if statement to prevent a null reference going through to that statement (as well as adding in some other conditions to tidy up the XML search).
for (Integer id : siteID){
site = em.find(SiteTable.class, id);
if(site != null && site.getPostcode() != null && !site.getPostcode().equals("")){
XMLPositionRetriever.runXMLQuery(site.getPostcode());
}
else{
System.out.println("The site and/or postcode against this Instruction does not exist.");
}
}
Thank you to MarioP, without whom I probably wouldn't have figured it out.