I have an issue that may in fact be a design issue but I am struggling to find a way around it.
In my sqlite database in my android application, I have a table called Customer. This has around 40 columns of various string and int data types. In practice, any of these columns may or may not be null.
In my code, I have a function simply called getCustomer(), which queries the database for a specific customer, and places all their cells from the database into a Customer class, which contains variables for each column. I can then pass that customer object around as I wish. The getCustomer() function returns this Customer object.
My problem is integers which may be null. I am familiar with how int cannot be null in java, but how Integer can be null. But my problem actually lies in the fact that the cells in the database can be empty (eg null).
For string columns, I simply do this:
Customer cust = new Customer();
cust.firstName = cursor.getString(0);
If cursor.getString(0); returns a null value, then the firstName variable is assigned null. Nice and simple. However with an int:
Customer cust = new Customer();
cust.daysSinceJoining = cursor.getInt(5);
The above crashes at run-time if daysSinceJoining is null. So I tried the following:
Customer cust = new Customer();
if (cursor.getInt(5) != null)
cust.daysSinceJoining = cursor.getInt(5);
However this gives me a compiler error, as you cannot use an int in a null comparison like that.
How can I get around this problem? How can I retrieve an int from an sqlite database when the int value could be null?
#sanders is right about the isNull() method and here's how you edit your code to use it:
Customer cust = new Customer();
if (!cursor.isNull(5))
cust.daysSinceJoining = cursor.getInt(5);
You could try the isNull() function.
Please take a look to that answer:
getInt null-constraints
I think that should work for you:
int lIndex = cursor.getColumnIndexOrThrow(COLUMN);
Integer lInteger = null;
if (!cursor.isNull(lIndex)
lInteger = cursor.getInt(lIndex);
You can create a cursor wrapper and add new functionality to the cursor class:
public class CustomCursor extends CursorWrapper {
public CustomCursor(Cursor cursor) { super(cursor); } //simple constructor
public Integer getInteger(int columnIndex) { // new method to return Integer instead of int
if (super.isNull(columnIndex)){
return null;
}else{
return super.getInt(columnIndex);
}
}
}
Example usage:
Cursor defaultCursor = db.rawQuery("select null,2 ", null);
defaultCursor.moveToFirst();
CustomCursor customCursor = new CustomCursor(defaultCursor);
customCursor.moveToFirst(); //custom cursor can do anything that default cursor can do
int defaultInt0 = defaultCursor.getInt(0); //nulls are usually converted into zero
int defaultInt1 = defaultCursor.getInt(1); //2 is correct
int customInt0 = customCursor.getInt(0); //these 2 are same as above , ie zero and 2
int customInt1 = customCursor.getInt(1);
Integer customInteger0 = customCursor.getInteger(0); // this will give a null Integer
Integer customInteger1 = customCursor.getInteger(1); // this will give a 2 Integer
Log.v("custom log.v call ", "lets see what outputs, null is usually converted to the word 'null' by the String.valueOf method :"
+String.valueOf(defaultInt0)+","+String.valueOf(defaultInt1)+","
+String.valueOf(customInt0)+","+String.valueOf(customInt1)+","
+String.valueOf(customInteger0)+","+String.valueOf(customInteger1)
);
//V: lets see what outputs, null is usually converted to the word 'null' by the String.valueOf method :0,2,0,2,null,2
if (cursor.getInt(5) !=0){
cust.daysSinceJoining = cursor.getInt(5);
}
or
int index = cursor.getColumnIndex(KEY_NAME);
Integer x = null;
if (!cursor.isNull(index)
cust.daysSinceJoining = cursor.getInt(5);
}
see the documentation
getInt() documentation:
Related
I would like to select a row from a table, but I only want to get one row and the row will be selected randomly.
I would like to select a row from a table, but I only want to get one row and the row will be selected randomly.
There isn't any special method calls which do this but there are ways that you can use the QueryBuilder to accomplish this.
If you have a numerical id, something like like should work:
qb = dao.queryBuilder();
qb.where().raw("id >= (ABS(RANDOM()) % MAX(id) + 1)");
entity = qb.queryForFirst();
Sqlite RANDOM() returns a large positive or negative integer. ABS() makes it just positive, MAX(id) allows us to then mod by the maximum id value. The +1 allows us to actually choose the max id row.
You can use queryRaw:
Relation result = null;
String query = "SELECT * from relations ORDER BY RANDOM() LIMIT 1";
try {
result = queryRaw(query, getRawRowMapper()).getFirstResult();
} catch (SQLException e) {
e.printStackTrace();
}
What I actually did was to get the List<> of the selected items from the database and then use a Random object, using the size() of the return list as the maxInt. And yes I did check for nulls.
Dao dao = getHelper().getObjectDao();
PreparedQuery<Object> query = dao.queryBuilder().[query].prepare();
Object object = null;
List<Object> resultList = dao.query(query);
if(resultList != null && resultList.size() > 0){
Random random = new Random();
int selected = random.nextInt(resultList.size() - 1);
object = resultList.get(selected);
}
It works for me:
dao.queryBuilder().orderByRaw("RANDOM()").queryForFirst();
How to check if table is empty using parse , I'm having a problem with the code below :
private String[] getMaxDateMessage() throws ParseException {
final String[] msgData = new String[3];
ParseObject ob = null;
String[] userIds = {currentUserId, recipientId};
ParseQuery<ParseObject> query = ParseQuery.getQuery("ParseMessage");
query.whereContainedIn("senderId", Arrays.asList(userIds));
query.whereContainedIn("recipientId", Arrays.asList(userIds));
query.orderByDescending("createdAt");
if(query.hasCachedResult())
{
ob = query.getFirst();
if (ob.isDataAvailable()) {
//for (int i = 0; i < 1; i++) {
//createdDate[0] = messageList.get(i).get("createdAt").toString();
msgData[0] = ob.getCreatedAt().toString();
msgData[1] = ob.get("senderId").toString();
msgData[2] = ob.get("recipientId").toString();
// }
}
}
The thing is that the table is empty , so the query should return null , but no exception is been throwed , it just crashes the app .
So how can I check if the table is empty before trying to fetch any data ?
Update : The solution that I have found is to use query.count().
If the count returns a value that is not 0 then the table is not empty .
Using query.count() to determine if the table is empty is not an optimal solution. While this is perfectly fine when actually run against an empty table, using query.count() will almost always result in a sub-optimal query when there's more than one object in the table. The reason for this is quite clear: you only care about the first object matched by this query, yet a query.count() will scan the whole table in order to return the total of objects that match your query.
Therefore, the ideal solution is to simply use query.getFirst() and check if you get any results. You should be able to handle the case where ob is not a ParseObject, e.g. the collection is either empty or no objects match your query.
Iam trying to find average of a column in my sqlite database.
Here is the code:
public void getAvgMileage(Prediction pd)
{
String [] columns = new String[]{KEY_ROW_ID, KEY_KM, KEY_FUEL_QTY, KEY_FUEL_PRICE, KEY_TOTAL_COST, KEY_MILEAGE, KEY_DATE,KEY_TANK_FULL};
predictionCursor = ourDatabase.rawQuery("SELECT AVG(_mileage) FROM fuel_table WHERE _mileage IS NOT NULL ORDER BY _id DESC LIMIT 5", null);
predictionCursor.moveToFirst();
if(predictionCursor!=null && predictionCursor.getCount()>0)
{
predictionCursor.moveToLast();
findAvgMileage = (Double.valueOf(predictionCursor.toString()));
pd.setpredictionMileage(findAvgMileage);
}
}
But Iam geting a NullPointerException.
Any help??
Thank you.
It doesn't look like you are getting the value out of the cursor for your SQL recordset
This line:
findAvgMileage = (Double.valueOf(predictionCursor.toString()));
looks like it's trying to take a double value of the tostring() of the actual cursor - which I don't think is going to usable or at least not parseable to Double. The return of Cursor.toString() may well be a null value.
replace the line with the following:
findAvgMileage = predictionCursor.getDouble(0);
This new line will fetch out the value in the first column of the current position of the curosr which in your SQL should be the average value you want.
I need to process a SQLite dataset in an Android system.
In my dataBaseHelper file (DataBaseAccessor) I have the following code (which when attached to a listview shows the relevant data).
public static ArrayList<QuestionListQuestion> getQuestionListQuestions(long id){
String qry = "select QuestionListQuestionID, QuestionListQuestionQuestionListID, QuestionListQuestionQuestionID, QuestionListQuestionSortOrder, QuestionListQuestionSupplementalQuestionIDYes, QuestionListQuestionSupplementalQuestionIDNo, QuestionListQuestionSupplementalQuestionIDText, QuestionListQuestionSurveyGroupID from QuestionListQuestion where QuestionListQuestionQuestionListID=" + id;
ArrayList<QuestionListQuestion> list = new ArrayList<QuestionListQuestion>();
try{
Cursor cursor = wdb.rawQuery(qry, null);
while (cursor.moveToNext()) {
QuestionListQuestion questionlistquestion = new QuestionListQuestion();
questionlistquestion.QuestionListQuestionID = cursor.getLong(0);
questionlistquestion.QuestionListQuestionQuestionListID = cursor.getLong(1);
questionlistquestion.QuestionListQuestionQuestionID = cursor.getLong(2);
questionlistquestion.QuestionListQuestionSortOrder = cursor.getLong(3);
questionlistquestion.QuestionListQuestionSupplementalQuestionIDYes = cursor.getString(4); questionlistquestion.QuestionListQuestionSupplementalQuestionIDNo = cursor.getString(5);
questionlistquestion.QuestionListQuestionSupplementalQuestionIDText = cursor.getString(6);
questionlistquestion.QuestionListQuestionSurveyGroupID = cursor.getLong(7);
list.add(questionlistquestion);
}
cursor.close();
}
catch (Exception e) {
e.printStackTrace();
}
return list;
}
I now need to extend the system so that I can process the data and create new records in another table based on the original list returned.
I tried the following attached to a button (selecting the relevant list ID from a spinner):-
QuestionListID = (String) SiteGenerateQuestions.this.spnQuestL.getSelectedItem().toString();
long SpinnerSelectedBT;
SpinnerSelectedBT = GenerateQuestions.this.spnQuestL.getSelectedItemId();
list = DatabaseAccessor.getQuestionListQuestions(SpinnerSelectedBT);
for (int i=0; i < list.size(); i++){
Toast.makeText(SiteGenerateQuestions.this," list.get(" + i + ") = " + list.get(i) + " " , Toast.LENGTH_SHORT).show();
}
The Toast displays the following:-
list.get(0) = com.tw.question.entity.QuestionListQuestion#407a6F70
list.get(1) = com.tw.question.entity.QuestionListQuestion#407bc170
etc...
How can I get access to the actual data instead of ... .entity.QuestionListQuestion#407bc170 or am I completely off-track?
Many Thanks
I agree with #wsanville the get() method will return the object in that location of the list. When you print out an object (in a toast, log, System.out.println etc) it will use the toString() value in the printout. The default toString() is the package name followed by # which is followed by a hex representation of that object. Your class will need to override the toString() method so when you use get() it will print out whatever you put in your toString() method.
The output you're seeing is because you haven't implemented the toString() method of your QuestionListQuestion class. Other than that, it seems like you do have the data you're looking for. Just try outputting the ID of your object, rather than concatenating the object itself (which will call toString() under the hood).
Also, since it looks like you're doing a database operation when a button gets clicked, make sure to do your database operations outside the UI thread. Check out the docs for a high level overview. You might want to use an AsyncTask for your database operation in question.
This is my first time using a database and I'm not really sure how this works. I made the database and made a query that returns a cursor and... now what? What is a cursor, really? Can I just use that to navigate through my data or do I have to put it in an ArrayList or ListActivity or what?
You need to iterate the cursor to get your results.
Use cursor.moveToFirst() and/or cursor.moveToNext() (with a while loop). Then you can use the getX() method, like cursor.getInt() or cursor.getString().
For example, ir your are expecting one result from your query:
if (cursor.moveToFirst()) {
String name = cursor.getString(cursor.getColumnIndex('NAME'));
int age = cursor.getInt(cursor.getColumnIndex('AGE'));
} else {
// oops nothing found!
}
First call cursor.moveToFirst(). Each time you call cursor.moveToNext() it will move to the next row. Make sure when you are done with your cursor you call cursor.deactivate() or you will get errors in your log cat.
Iterate over the returned Cursor instance
public List<Object[]> cursorToTableRows(Cursor cursor) {
List<Object[]> result = new ArrayList<Object[]>(cursor.getCount());
cursor.move(0);
cursor.moveToNext();
while (cursor.isAfterLast() == false) {
Object[] tableRow = new Object[cursor.getColumnCount()];
for(int i=0; i<cursor.getColumnNames().length; i++) {
int columnIndex = cursor.getColumnIndex(cursor.getColumnName(i));
String columnValue = cursor.getString(columnIndex);
tableRow[i] = columnValue;
}
result.add(tableRow);
cursor.moveToNext();
}
cursor.close();
return result;
}
Then create the desired objects.
public List<Vehicle> getVehicles() {
List<Vehicle> vehicles = new ArrayList<Vehicle>();
Cursor cursor = null;
List<Object[]> objects = cursorToTableRows(cursor);
for(Object[] row : objects) {
int i=0;
Vehicle vehicle = new Vehicle(row[i++].toString(), row[i++].toString()));
vehicles.add(vehicle)
}
return vehicles;
}
from Developer.android: This interface provides random read-write access to the result set returned by a database query.
In other words: query returns you a set of data represented by a cursor. First you need to make sure you got a valid cursor (not null) and then try to move it to desired position in the data set (use moveToXXX methods). In order to obtain data pointed by cursor use getXXX methods. When done using it make sure to call close to release resources.
According to this link it looks like you can iterate through the query return using something like:
cursor.next();
And grab the data at the location you are looking for using:
cursor.getString(0)
After you successfully have your Cursor setup, you would typically want to display that to a view in some form.
Have a look at the following answer for a detailed, but simple example of using a Cursor Adapter to pair up your newly-minted Cursor with your desired XML View:
https://stackoverflow.com/a/20532937/293280