I'm developing an Android application and I would like to keep my SQLite query statements outside of my Java classes.
I considered using a .properties file, in which to store all of my SQL statements. Sounds fine, each property in a .properties file holds a string - I can even store prepared statements and give them the needed parameters, for example:
get.student.with.first.name=SELECT * FROM Students WHERE FirstName = ?;
However, I have also implemented Persistence Contracts for my database tables like so:
public final class StudentPersistenceContract {
private StudentPersistenceContract() {}
public static abstract class StudentEntry implements BaseColumns {
public static final String TABLE_NAME = "Student";
public static final String COLUMN_FIRST_NAME = "FirstName";
public static final String COLUMN_LAST_NAME = "LastName";
}
}
I wouldn't want to hardcode the table and column names into the entries of the .properties file, I would like to access them dynamically like so: StudentPersistenceContract.StudentEntry.TABLE_NAME, etc.
One thing I thought of was creating a class which can't be instantiated in which to "construct" the queries I need. Something along the lines of...
public final class SqlQueryConstructor {
private SqlQueryConstructor() {}
public static final String GET_STUDENT_WITH_FIRST_NAME = "SELECT * FROM " + StudentPersistenceContract.StudentEntry.TABLE_NAME + " WHERE " + StudentPersistenceContract.StudentEntry.COLUMN_FIRST_NAME + " = ?;";
}
This way I can get the desired SQL query by accessing: SqlQueryConstructor.GET_STUDENT_WITH_FIRST_NAME
This is still a Java class, but it'll be good to know that all of my SQL is there and not scattered around all over the place.
Is this a good idea? Are there any other alternatives?
I have decided to use my second approach - using a class with static fields for the SQLite statements. I read about when it's good to use strings.xml and when to use static final Strings: android - strings.xml vs static constants, Android strings, Should I use strings.xml or java strings, etc.
So I'll use strings.xml for localization and the class with static fields for the SQL statements.
Related
When we concatenate compile-time static Strings using the + operator, the compiler will join them together and store a new static string in its place.
Now I have a strategy pattern that supplies SQL fragments that should be concatenated into a larger SQL statement. All the pieces are static, but since there are method calls involved the above compile-time joining does not happen.
Example:
class MagicDao {
void Object daoMethod(GetStuff cmd) {
String sql = "select ... where " + cmd.getWhereClause() + " order by ...";
// ...
}
}
public interface GetStuff {
String getWhereClause();
Object[] getParameters();
}
class GetFunStuff implements GetStuff {
public String getWhereClause() {
return " abc = ? ";
}
// ...
}
I am wondering is there any pattern/trick that will make the SQL string concatenation compile-time again while retaining the simplicity/readability of the code above.
(If caching is the only solution, could one suggest a readable, thread-safe one liner?)
(Motivation for doing this: making things static will save countless garbage being created each second during the string building process and saves the time looking up the string in the PreparedStatement cache.)
I don't really know how you're making SQL queries, but you could consider to use JDBC PreparedStatement, like:
PreparedStatement pstmt = con.prepareStatement("select ... where ? order by ...");
pstmt.setString(1, cmd.getWhereClause());
in this case your String will be precompiled
I have an old doubt about constants in Java Projects maintenance. From my perspective, when we try putting the constants inside an Abstract class like that:
public final class MyConstants {
public static final String CONSTANT1 = "const1";
public static final String CONSTANT2 = "const2";
public static final String CONSTANT3 = "const3";
public static final String CONSTANT4 = "const4";
}
after that using those constants inside classes in the project:
public void myMethod(final Map params) {
final String myparam = (String) params.get(MyConstants.CONSTANT1);
//DO SOMETHING WITH PARAMS
}
It leads to boiler plate code, verbose use of constants and no real advances. In other hand if we put those constants inside the class for somehow people don't like it. They say "what about we have the same constant declare somewhere?" the problem is maintainance issues, if we change those constants in that class the change can be visible on several parts without any big problem.
Those constants are mainly used for mapping webservices for java perspective without having to generating POJOs like JAXB based on WSDL, the webservices operations are mapped directly for key value maps in Java.
I want to know what do you think about this approach and if we have any other choice.
Thank you.
If I understand your concern, don't hardcode those constants as values except perhaps as defaults and store them with Properties and/or ResourceBundle(s). You might also read the Java Tutorial on Properties. Something like,
Properties props = new Properties();
FileInputStream in = new FileInputStream("my.proprties");
props.load(in);
String v = props.get("CONSTANT_ONE", "const1"); // <-- the "1" is a default.
Then if you need to change the property later you only have to modify the properties file.
Is there a method in which I can retrieve all the data from a particular database column and store it in a string array?
My database currently looks like this:
public class DatabaseTotalEntries {
public static final String KEY_ROWID = "_id";
public static final String KEY_NAME = "appliance_name";
public static final String KEY_TOTAL_TIME = "appliance_running_time";
public static final String KEY_TOTAL_COST = "appliance_cost_usage";
public static final String KEY_TOTAL_ENERGY = "appliance_energy_usage";
private static final String DATABASE_NAME = "ApplianceTotaldb"; // The name of the database
private static final String DATABASE_TABLE = "AllEntries"; // The name of the database table
private static final int DATABASE_VERSION = 1;
and I am looking to create a method in which the data under the column 'KEY_TOTAL_COST' for every row/entry in the database is retrieved and stored in a String array
Any hep would be appreciated
Use standard way to retrieve data from DB via JDBC driver for your database. Create prepared statement, execute it upon created connection and pull data from result set object. As mentioned in Mihai Todor's answer, in SQL query, select only KEY_TOTAL_COST, it will be faster if you query only for columns that you're interested in. When you pull data from result set, you can put it into whatever data structure you want, and manipulate it as you need (truncate, split, convert to numbers and so on ...)
You might find this tutorial useful:
http://docs.oracle.com/javase/tutorial/jdbc/basics/retrieving.html
... or simply try looking on google for more of "JDBC result set" usage examples.
Well, the SQL statement that you need to use is this: select appliance_running_time from ApplianceTotaldb.AllEntries. In order to run it, I guess it depends on the RDBMS that you are using. Is it MySQL? Try to search for a JDBC tutorial on Google...
I'm new to Android & Java programming but have been programming in .NET for many years. We've recently developed an android app and it's now in the final stage to be prepped for the customer (not via the market/google play btw). At any rate, while cleaning up the code. I've noticed we use a TON of strings and I'd like to cut down on this if possible. I've read a few articles and took the suggestion that anything the end-user may see, I put it in the strings.xml (for better localization, not too sure what they mean by that) but we also use SQLite table names, column names, etc. and I'd like to know the best way to construct a class (or set of classes) that allows us (my developers and I) to access them with ease.
This is how I started to construct it but wanted some opinions as to if there's a better way (design, performance issues, etc.)
public class Constants {
static enum SQLiteTableNames { Issues, Activities }
static class SQLiteTables {
static class Issues {
static class ColumnNames {
static String ID = "_id";
static String DateReceived = "DateReceived";
}
}
static class IssueActivites {
static class ColumnNames {
static String ID = "_id";
static String IssueID = "IssueID";
static String ActivityDate = "ActivityDate";
static String ActivityType = "ActivityType";
static String FullName = "FullName";
static String Notes = "Notes";
}
}
}
}
This allows us to reference column names like so:
Constants.SQLiteTables.IssueActivites.ColumnNames.ActivityDate;
Should I use final static on the properties instead of just static?
Constants should be static final. This does have a performance benefit, as it allows the value to be compiled in. It's also just good style.
By the way, the convention is to put constant names in ALL_CAPS.
How will I be able to retrieve the value of a variable which has a dynamic name
For Example I have list of constants
public class Constant{
public static final String S_R = "Standard(240)";
public static final String S_W = "Standard(180)";
public static final String L_R = "Large(360)";
public static final String L_W = "Large(280)";
}
Based on database I build a variable name
String varName = "S" + "_" +"R"; // This can be S_R , S_W , L_R or L_W
String varVal = // How do i get value of S_R
Use a normal HashMap with variable names as strings against their values. Or use a EnumMap with enums as key and your value as values. AFAIK, that's the closest you can get when using Java. Sure, you can mess around with reflection but IMO the map approach is much more logical.
You can use a Map<String, String> and locate the value by its key.
Even better, you can have an enum:
public enum Foo {
S_R("Standard", 240),
S_W("Standard", 180),...;
private String type;
private String duration;
// constructor and getters
}
And then call Foo.valueOf(name)
(You can also do this via reflection - Constants.class.getField(fieldName) and then call field.get(null) (null for static). But that's not really a good approach.)
If you really must do this (and it's unlikely), you would have to use the Java "reflection" APIs.