SQlite database not storing double value as string - java

I am using following code
public boolean addArea(AreaClass area , ArrayList<AreaMarkClass> areaArray)
{
area.id = getNextAreaId();
Log.d("longitude", area.longitude);
Log.d("latitude", area.latitude);
ContentValues initialValues = new ContentValues();
initialValues.put("_id", area.id);
initialValues.put("name", area.name);
initialValues.put("longitude", area.longitude);
initialValues.put("latitude", area.latitude);
initialValues.put("zoomLevel", area.zoomLevel);
initialValues.put("creationDate",area.creationDate);
try
{
mDb.insertOrThrow("TTArea", null, initialValues);
}
area.longitude is a string whose value is obtained by String.value (A Double Value)
Now usually it is something like this 22.323434523464563456
however when i try to retrieve this value
public AreaClass getAreaClassWithAreaId(Integer id)
{
String queryString = "SELECT * FROM TTArea WHERE _id = ?";
Cursor resultSet = mDb.rawQuery(queryString, new String[]{id.toString()});
AreaClass area = new AreaClass();
while(resultSet.moveToNext())
{
area = new AreaClass(
resultSet.getInt(resultSet.getColumnIndex("_id")),
resultSet.getString(resultSet.getColumnIndex("name")),
resultSet.getString(resultSet.getColumnIndex("longitude")),
resultSet.getString(resultSet.getColumnIndex("latitude")),
resultSet.getString(resultSet.getColumnIndex("zoomLevel")),
resultSet.getString(resultSet.getColumnIndex("creationDate"))
);
}
resultSet.close();
return area;
}
it somehow rounds it to 22.3234. In my app i need precise what i am storing. What is this behavior and how can i resolve this?

I use these methods when working with SQLite:
public static Double stringToDouble (String x)
{
if (x !=null)
return Double.parseDouble(x);
return null;
}
public static String doubleToString (Double y)
{
if (y != null)
return String.valueOf(y);
return null;
}
When adding to database transform the double value to string and vice-versa, and please tell me if this solution works
EDIT: The solution is in comments:
"I see you created your table with STRING fields. You can try with TEXT type, works for me."

Related

List DataModel reads just the last element

I have a database created with location updates and in the database there is a bunch of locations x and y. and in the second method readFirestore() reads the location data and compares the favorite locations which came from sqlite database and if the favorite location is near the data from firestore it writes the campaign name which is on the same location to another database. But when I want to compare the favorite location in the firestore methot, there is just the last item of the database. I looked with the Log.
Code 1:
public List<DataModel> listFavoriteLocation(){
db = new DatabaseHelper(this);
SQLiteDatabase mydb = db.getWritableDatabase();
List<DataModel> data=new ArrayList<>();
Cursor csr = mydb.rawQuery("select * from "+TABLE+" ;",null);
StringBuffer stringBuffer = new StringBuffer();
DataModel dataModel = null;
while (csr.moveToNext()) {
dataModel= new DataModel();
String FAVCurrentLocationLAT = csr.getString(csr.getColumnIndexOrThrow("FAVCurrentLocationLAT"));
String FAVCurrentLocationLONG = csr.getString(csr.getColumnIndexOrThrow("FAVCurrentLocationLONG"));
dataModel.setFAVCurrentLocationLAT(FAVCurrentLocationLAT);
dataModel.setFAVCurrentLocationLONG(FAVCurrentLocationLONG);
stringBuffer.append(dataModel);
data.add(dataModel);
}
for (DataModel mo:data ) {
this.List_FAVCurrentLocationLAT = mo.getFAVCurrentLocationLAT();
this.List_FAVCurrentLocationLONG = mo.getFAVCurrentLocationLONG();
Log.i("helloLAT",""+List_FAVCurrentLocationLAT); //OK
Log.i("helloLONG",""+List_FAVCurrentLocationLONG); //OK
// This section writes the favorite locations seperately to the log.
}
return data;
}
Code 2:
public void readFirestore() {
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collection("campaigns")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
private String FSname,FScityLAT,FScityLONG,FScampaignStartDate,FScampaignEndDate;
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful() && task.getResult() != null) {
for (QueryDocumentSnapshot document : task.getResult()) {
String name = document.getString("name");
String cityLAT = document.getString("cityLAT");
String cityLONG = document.getString("cityLONG");
String campaignStartDate = document.getString("campaignStartDate");
String campaignEndDate = document.getString("campaignEndDate");
this.FSname = name;
this.FScityLAT = cityLAT;
this.FScityLONG = cityLONG;
this.FScampaignStartDate = campaignStartDate;
this.FScampaignEndDate = campaignEndDate;
listFavoriteLocation();
String FS_FAVCurrentLocationLAT = List_FAVCurrentLocationLAT;
String FS_FAVCurrentLocationLONG = List_FAVCurrentLocationLONG;
Log.i("hellolist",""+List_FAVCurrentLocationLAT); // just writes the last loc item from sqlite
double FS_FAVCurrentLocationLAT_double = Double.parseDouble(FS_FAVCurrentLocationLAT); // Fav Loc DB
double FS_FAVCurrentLocationLONG_double = Double.parseDouble(FS_FAVCurrentLocationLONG); double FScityLAT_double = Double.parseDouble(FScityLAT); // Campaign Loc Firestore LAT
double FScityLONG_double = Double.parseDouble(FScityLONG);
double theta = FScityLONG_double - FS_FAVCurrentLocationLONG_double;
double dist = Math.sin(Math.toRadians(FS_FAVCurrentLocationLAT_double)) * Math.sin(Math.toRadians(FScityLAT_double)) + Math.cos(Math.toRadians(FS_FAVCurrentLocationLAT_double)) * Math.cos(Math.toRadians(FScityLAT_double)) * Math.cos(Math.toRadians(theta));
dist = Math.acos(dist);
dist = Math.toDegrees(dist);
dist = dist * 60 * 1.1515;
dist = dist * 1.609344;
if (dist <= 0.5) // 500 meter
{
SQLiteQueryFavCampaign = "INSERT OR REPLACE INTO myTable3(FAVCampaignName, FAVCampaigncampaignStartDate, FAVCampaigncampaignEndDate)" + " VALUES('"+FSname+"','"+FScampaignStartDate+"','"+FScampaignEndDate+"');";
SQLITEDATABASEFavCampaign.execSQL(SQLiteQueryFavCampaign);
Log.i("helloname",""+FSname);
}
}
} else {
}
}
});
Toast.makeText(CampaignActivity.this,"Creating", Toast.LENGTH_SHORT).show();
}
If I understand correctly: the listFavoriteLocation method properly retrieves the data you're expecting from the database. If you take a look at the rest of your code, you'll see that you are iterating over the list of data and overwriting your instance variables with them, one-by-one, until the list has been fully iterated over, meaning you will only preserve the last element in your instance once you've left the method.
So, to be clear, the following block will properly log every element, but only the values of the last element will be preserved in the two instance variables you're using (FAVCurrentLocationLAT and FavCurrentLocationLong):
for (DataModel mo:data ) {
this.List_FAVCurrentLocationLAT = mo.getFAVCurrentLocationLAT();
this.List_FAVCurrentLocationLONG = mo.getFAVCurrentLocationLONG();
Log.i("helloLAT",""+List_FAVCurrentLocationLAT); //OK
Log.i("helloLONG",""+List_FAVCurrentLocationLONG); //OK
// This section writes the favorite locations seperately to the log.
}
What you need to do is use the returned data list being loaded in the listFavoriteLocation method, and then manipulate it in the following code as you wish.
So, for example:
List<DataModel> data = listFavoriteLocation();
for (int i = 0; i < data.size(); i++) {
DataModel dataModel = data.get(i);
log.i("Data model "+i+": "+dataModel);
// Do work on each data model element here
}

Why doesn't this .equals() work?

I'm working in Eclipse (Android). In the following blocks, EmployeeInt and RestaurantInt are data types and query() opens a connection to the database and parses the results. When I print the query results, I get identical strings, but the boolean is still false. I've tried trimming the strings, but that didn't help.
public boolean verifyEmployee(String email, String password) {
ArrayList<EmployeeInt> employeeEmailID = query("SELECT employeeID FROM employees WHERE emailAddress = \'"+email+"\'");
ArrayList<EmployeeInt> employeePasswordID = query("SELECT employeeID FROM employees WHERE password = \'"+password+"\'");
String stringEmployeeEmailID = employeeEmailID.toString();
String stringEmployeePasswordID = employeePasswordID.toString();
if(stringEmployeeEmailID.equals(stringEmployeePasswordID)) {
return true;
} else {
return false;
}
}
Executing the above gives me false, while executing the following block (virtually identical) gives me true.
public boolean verifyRestaurant(String email, String password) {
ArrayList<RestaurantInt> restaurantEmailID = query("SELECT restaurantID FROM restaurants WHERE emailAddress = \'"+email+"\'");
ArrayList<RestaurantInt> restaurantPasswordID = query("SELECT restaurantID FROM restaurants WHERE password = \'"+password+"\'");
String stringRestaurantEmailID = restaurantEmailID.toString();
String stringRestaurantPasswordID = restaurantPasswordID.toString();
if(stringRestaurantEmailID.equals(stringRestaurantPasswordID)) {
return true;
} else {
return false;
}
}
Can anyone point out my mistake?
EDIT
I changed it to this and it worked:
public boolean verifyEmployee(String email, String password) {
ArrayList<EmployeeInt> employeeEmailID = query("SELECT * FROM employees WHERE emailAddress = \'"+email+"\'");
ArrayList<EmployeeInt> employeePasswordID = query("SELECT * FROM employees WHERE password = \'"+password+"\'");
int intEmployeeEmailID = employeeEmailID.get(0).getID();
int intEmployeePasswordID = employeePasswordID.get(0).getID();
if(intEmployeeEmailID==intEmployeePasswordID) {
return true;
} else {
return false;
}
}
I know I could also use return (condition), but I would like to add some messages if the login fails, something like:
System.err.println("email address and password do not correspond");
I'm not making an app to publish, it's merely for an assignment. Thanks for the help!
You are calling toString() on an ArrayList. Two different ArrayList objects will return two different toString() strings. You probably meant to get the first element of the ArrayList, and convert THAT to a string.
Example
EmployeeInt is your custom object. In my example, I assume it has some int field that can be retreived with getID().
ArrayList<EmployeeInt> idList = query("SELECT employeeID FROM employees WHERE emailAddress = \'"+email+"\'");
int ID = idList.get(0).getID();
stringEmployeeEmailID = String.valueOf(ID);
This may be easier to read than code:
query() returns an ArrayList
We extract the first element of the ArrayList - this is the part you left out
We get the ID of that element
We convert it to a String

GreenDao whereOr and conditions adding in a loop

I need to add some or clauses to query. I need to do it in a loop.
StringTokenizer st = new StringTokenizer(symptoms, ",");
while(st.hasMoreTokens()){
qb.whereOr(Properties.Symptom.like("%" + st.nextToken() + "%"));
}
How I can add those or conditions properly, because this above is not working as expected. I want to add or for every symptom.
If you look at the documentation, you'll see that whereOr() takes an unbounded number of conditions. What you want to do is add them all at once in an array:
StringTokenizer st = new StringTokenizer(symptoms, ",");
ArrayList<WhereCondition> whereConditions = new ArrayList<WhereCondition>();
while(st.hasMoreTokens()){
whereConditions.add(Properties.Symptom.like("%" + st.nextToken() + "%"));
}
// Give the ArrayList an already allocated array to place its contents in.
WhereCondition[] conditionsArray = new WhereCondition[whereConditions.size()];
conditionsArray = whereConditions.toArray(conditionsArray);
qb.whereOr(conditionsArray);
It looks like the method call in the documentation takes two non-array WhereConditions and then an ellipsized argument, which accepts an array or an additional comma-separated list of objects. So you might have to do something like this to get it to work properly:
qb.whereOr(conditionsArray[0], conditionsArray[1], Arrays.copyOfRange(conditionsArray, 2, conditionsArray.length));
ADDENDUM: It looks like you're using APIs that don't match the documentation, possibly an older version of greenDAO. I wrote this solution based off the current documentation. I can't guarantee that it will work for you. I recommend updating if possible.
Try this:
StringTokenizer st = new StringTokenizer(symptoms, ",");
WhereCondition where = null;
while(st.hasMoreTokens()){
if (where != null) {
where = qb.or(where, Properties.Symptom.like("%" + st.nextToken() + "%"));
} else {
where = Properties.Symptom.like("%" + st.nextToken() + "%");
}
}
qb.where(where).list();
I had the same problem so I added my own method in an Util class to perform the same behavior when I have one or several WhereCondition in an array.
Here is my gateway method :
public static QueryBuilder whereOr(QueryBuilder queryBuilder, WhereCondition[] whereConditions){
if(whereConditions == null) return queryBuilder.where(null);
else if(whereConditions.length == 1) return queryBuilder.where(whereConditions[0]);
else return queryBuilder.whereOr(whereConditions[0], whereConditions[1], Arrays.copyOfRange(whereConditions, 2, whereConditions.length));
}
Use : Util.whereOr(queryBuilder, whereConditionsArray);
Default : Can't use the Builder Pattern from the QueryBuilder with this approach
(More later) Here, I share you some code which could spare you time when developping DAO methods.
public class QueryBuilderUtil {
public static final String EQ = "=?";
public static final String NOTEQ = "<>?";
public static final String LIKE = " LIKE ?";
public static final String GE = ">=?";
public static final String LE = "<=?";
public static final String GT = ">?";
public static final String LT = "<?";
public static QueryBuilder whereOrOnSamePropertyWithDifferentValues(QueryBuilder queryBuilder, Property property, String operation, String values, String separator) {
return whereOrOnSamePropertyWithDifferentValues(queryBuilder, property, operation, values.split(separator));
}
public static QueryBuilder whereOrOnSamePropertyWithDifferentValues(QueryBuilder queryBuilder, Property property, String operation, String[] values) {
WhereCondition[] whereConditions = new WhereCondition[values.length];
int i = 0;
for (String value : values) {
whereConditions[i++] = new WhereCondition.PropertyCondition(property, operation, value);
}
return whereOr(queryBuilder, whereConditions);
}
public static QueryBuilder whereOr(QueryBuilder queryBuilder, WhereCondition[] whereConditions) {
if (whereConditions == null) return queryBuilder.where(null);
else if (whereConditions.length == 1) return queryBuilder.where(whereConditions[0]);
else return queryBuilder.whereOr(whereConditions[0], whereConditions[1], Arrays.copyOfRange(whereConditions, 2, whereConditions.length));
}
}
With this class, you can perform a whereOr with the same property on multiples "values string" in one line. It was necessary to clean my code :). However you can only do simple operations like variables declared in the class.
Example :
public List<Block> loadAllByModId(String mods_id) {
synchronized (this) {
QueryBuilder<Block> queryBuilder = queryBuilder();
QueryBuilderUtil.whereOrOnSamePropertyWithDifferentValues(queryBuilder, Properties.ModId, QueryBuilderUtil.EQ, mods_id, ";");
query_list = queryBuilder.build();
}
Query<Block> query = query_list.forCurrentThread();
return query.list();
}
Hope it helps

SQL Error when tried to enter data using netbeans

First, I'll give the codes I'm dealing with.
Action code for the "Save" Button.
private void saveBtActionPerformed(java.awt.event.ActionEvent evt) {
try {
Production production=new Production(batchNoValueLabel.getText(), productIDCombo.getSelectedItem(), rawMaterialUsedCombo.getSelectedItem(), dateValueLabel.getText(), rawMaterialBatchCombo.getSelectedItem(), weightInitialSpinner.getValue(), beforeWeightSpinner.getValue(), afterWeightSpinner.getValue(), finalWeightSpinner.getValue(), packingWeightSpinner.getValue(), noOfUnitSpinner.getValue(), wastageSpinner.getValue());
int res=ProductionController.addBatch(production);
if(res==1){
JOptionPane.showMessageDialog(this, "New Batch Added!");
String nextid = IDGeneration.getNextid("B", "production", "productionBatchID");
batchNoValueLabel.setText(nextid);
productIDCombo.removeAllItems();
ArrayList<String> getProductsDetails = ProductsController.getProductID();
for (String detail : getProductsDetails) {
productIDCombo.addItem(detail);
}
}else{
JOptionPane.showMessageDialog(this, "New Product Adding Failed!");
}
} catch (ClassNotFoundException | SQLException ex) {
Logger.getLogger(ProductsForm.class.getName()).log(Level.SEVERE, null, ex);
}
}
Then, the Model Class. (Getters and Setters are there, not pasted here)
public Production(String productionBatchID, Object finishedMaterialID, Object rawMaterialID, String productionDate, Object rawMatBatchID, Object initialWeight, Object beforeWeight, Object afterWeight, Object finalWeight, Object packingWeight, Object noOfUnits, Object wastage) {
this.productionBatchID = productionBatchID;
this.finishedMaterialID = (String) finishedMaterialID;
this.rawMaterialID = (String) rawMaterialID;
this.productionDate = productionDate;
this.rawMatBatchID = (String) rawMatBatchID;
this.initialWeight = (int) initialWeight;
this.beforeWeight = (int) beforeWeight;
this.afterWeight = (int) afterWeight;
this.finalWeight = (int) finalWeight;
this.packingWeight = (int) packingWeight;
this.noOfUnits = (int) noOfUnits;
this.wastage = (int) wastage;
}
And, finally the controller class.
public class ProductionController {
public static int addBatch(Production production) throws ClassNotFoundException, SQLException {
Connection conn=DBConnection.getConnection();
Statement stm=conn.createStatement();
String sql="insert into production (productionBatchID, finishedMaterialID, rawMaterialID, productionDate, rawMatBatchID, initialWeight, beforeWeight, finalWeight, packingWeight, noOfUnits, wastage) values ('"+production.getProductionBatchID()+"','"+production.getFinishedMaterialID()+"','"+production.getRawMaterialID()+"','"+production.getProductionDate()+"','"+production.getRawMatBatchID()+"','"+production.getInitialWeight()+"','"+production.getBeforeWeight()+"','"+production.getAfterWeight()+"','"+production.getFinalWeight()+"','"+production.getPackingWeight()+"','"+production.getNoOfUnits()+"','"+production.getWastage()+"');";
int rowCount=stm.executeUpdate(sql);
return rowCount;
}
}
And still, when I enter data in the GUI and try to send the data to the database, it gives out "java.sql.SQLException: Column count doesn't match value count at row 1" error. How to solve this? Oh, and here's the MySQL Table:
create table production(productionBatchID VARCHAR(4) NOT NULL,finishedMaterialID VARCHAR(4) NOT NULL,rawMaterialID VARCHAR(4) NOT NULL,productionDate VARCHAR(15),rawMatBatchID VARCHAR(4),initialWeight INT(5),beforeWeight INT(5),afterWeight INT(5),finalWeight INT(5),packingWeight INT(5),noOfUnits INT(5),wastage INT(5),CONSTRAINT PRIMARY KEY (productionBatchID))ENGINE=INNODB;
How to solve this?
Your VALUES clause has
'"+production.getAfterWeight()+"','"+production.getFinalWeight()+
But you only have finalWeight in the column list.
The error tells you this
insert into production (
productionBatchID, finishedMaterialID,
rawMaterialID, productionDate,
rawMatBatchID, initialWeight,
beforeWeight, finalWeight,
packingWeight, noOfUnits,
wastage)
values (
'"+production.getProductionBatchID()+"','"+production.getFinishedMaterialID()+"','"+
production.getRawMaterialID()+"','"+production.getProductionDate()+"','"+
production.getRawMatBatchID()+"','"+production.getInitialWeight()+"','"+
production.getBeforeWeight()+"','"+
production.getAfterWeight()+"','"+
production.getFinalWeight()+"','"+ there are 3 here
production.getPackingWeight()+"','"+production.getNoOfUnits()+"','"+
production.getWastage()+"');";
Also, parameterise your queries to mitigate SQL Injection risks please
There is mismatch in number of columns you are using in INSERT query, 'beforeWeight' is the column, whose values is missing, below is the corrected query:
String sql="insert into production (productionBatchID, finishedMaterialID, rawMaterialID, productionDate, rawMatBatchID, initialWeight, **beforeWeight**, finalWeight, packingWeight, noOfUnits, wastage) values ('"+production.getProductionBatchID()+"','"+production.getFinishedMaterialID()+"','"+production.getRawMaterialID()+"','"+production.getProductionDate()+"','"+production.getRawMatBatchID()+"','"+production.getInitialWeight()+"','"+production.getBeforeWeight()+"','"+production.getAfterWeight()+"','"+production.getBeforeWeight()+"','"+production.getFinalWeight()+"','"+production.getPackingWeight()+"','"+production.getNoOfUnits()+"','"+production.getWastage()+"');";

NSNotFound equivalent in Java

I need to know if there is a way to say that int type is not found in Java Android.
I'm writing an android application,which is actually written first for Iphone, and have a little issue. At some point I have to check if the int type which returns a method is not found and if it's true do some calculations. The problem is that when I did that in Java as if(Id==0) it's throwing me an exception even if the Id is 0.
this is my method :
private static int localUserIdByServerUserId(int serverUserId, String serverName){
dbHelper = new DataBaseHelper(context, "stampii_sys_tpl.sqlite", null, 1);
dbHelper.getDatabase();
String query = "SELECT id FROM users WHERE objectId = "+serverUserId+" AND serverName = '"+serverName+"' LIMIT 1";
ArrayList<String> result = new ArrayList<String>();
cursor = dbHelper.executeSQLQuery(query);
cursor.moveToFirst();
while(!cursor.isAfterLast()) {
result.add(cursor.getString(cursor.getColumnIndex("id")));
cursor.moveToNext();
}
Log.i("result ","Result : "+result.toString());
Log.i("CURSOR ","Cursor Position : "+cursor.getPosition());
int uuid = Integer.parseInt(result.get(cursor.getColumnIndex("objectId")+1));
Log.w("localUSerByIdServerUserId","LocalUserByIdServerUserId result : "+uuid);
cursor.close();
return uuid;
and here is how I'm using it :
int uuId = rpc.lUserIdByServerUserId(userId,newServerName);
Log.w("uuId","uuId : "+uuId);
if(uuId==0){
// do some calculations
}
Any suggestions ?
lUserIdByServerUserId() could throw an exception when the user is not found.
e.g.
try {
int uuId = rpc.lUserIdByServerUserId(userId,newServerName);
Log.w("uuId","uuId : "+uuId);
}
catch (NotFoundException nfe) {
// do some calculations
}
You will need to modify lUserIdByServerUserId() to throw the exception. You may also need to define your own NotFoundException class if a suitable exception doesn't already exist in the Java libraries.
EDIT:
Alternatively, following on from #mthpvg's answer, you could change lUserIdByServerUserId() to return an Integer type, which can be set to null if not found and tested.
e.g.
Integer uuId = rpc.lUserIdByServerUserId(userId,newServerName);
if (uuId == null) {
// Do some calculations
}

Categories

Resources