ORMLite Select Distinct Fields - android

I have a SQLite table (on Android) that has numerous fields, but certain fields are repeated/denormalized. I would like to select a distinct set of this data and use them as actual objects.
Example
books table
title summary author
Little Johnny A funny kid Johnny Himself
Big Johnny A funny adult Johnny Himself
I would like to extract one author from this list ("Johnny Himself") and would expect I should be able to do this with ORMLite instead of manually with Java.

I would like to select a distinct set of this data and use them as actual objects.
ORMLite supports a distinct() method on the QueryBuilder that should do what you want. So your code would look something like:
List<Book> results = booksDao.queryBuilder()
.distinct().selectColumns("author").query();
In this case, the resulting Book objects would only have the author field set and not the id field or anything else. If you just wanted the author names instead of objects then you could do:
GenericRawResults<String[]> rawResults =
booksDao.queryRaw("SELECT DISTINCT author FROM books");
for (String[] resultColumns : rawResults) {
String author = resultColumns[0];
...
}

This is my application code
public class DbHelper<T> {
private Class<T> c;
private DatabaseHelper db;
public DbHelper(Class<T> c) {
this.c = c;
db = DatabaseHelper.getInstance();
}
This is a good idea
public List<T> queryForBuilderDistinct(int offset, int limit, String ColumnsName,
String orderName, boolean isAsc) {
try {
Dao<T, Integer> dao = db.getDao(c);
QueryBuilder<T, Integer> queryBuilder = dao.queryBuilder();
if (offset != 0) {
queryBuilder.offset((long) offset);
}
if (limit != 0) {
queryBuilder.limit((long) limit);
}
if (orderName != null) {
queryBuilder.orderBy(orderName, isAsc);
}
queryBuilder.distinct().selectColumns(ColumnsName);
return dao.query(queryBuilder.prepare());
} catch (SQLException e) {
LogUtil.e(TAG, "queryForBuilderDistinct", e);
}
return new ArrayList<T>();
}

Related

Android sqllite, querying an object that is a property of another object

How do I query an object that has another object as a property? I need to get the values of the property as well. Here's my model:
public class Department {
public int DeptId;
public string DeptName;
}
public class Employee {
public int Id;
public string Name;
public int DeptId;
public Department Department;
}
I'm coming from a c# background, and I could do this with c# using Entity Framework. Now it seems like this model works but when I included a sqllite functionality for the objects I'm not sure how to query it.
Here's my first try, but I'm not sure if this is the best way
public List<Employee> getAllEmployeesWithDepartments(){
List<Employee> employees = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("SELECT * FROM Employee e LEFT JOIN Department d on e.DeptId = d.Id" , null);
if(res.moveToFirst()){
do{
Employee emp = new Employee();
emp.Id = res.getInt(res.getColumnIndex("Id"));
emp.Name = res.getString(res.getColumnIndex("Name"));
Department dep = new Department();
dep.Id = res.getInt(res.getColumnIndex("Id"));
dep.Name = res.getString(res.getColumnIndex("Name"));
emp.Department = dep;
employees.add(emp);
}while (res.moveToNext());
}
return employees;
}
You're confused. SQLite doesn't have objects. Its a table based database (like almost all databases). You can map objects into tables, but you have to create those mappings yourself. Since SQLite doesn't have objects, it definitely doesn't have subobjects. You generally make something like it by joining another table with a foreign key constraint on the main table, but it really is defined by your schema. There is no generic answer for you.

SQLite sort by integer value

I'm using ActiveAndroid library. I need to get a list of my objects sorted by the integer field. here is how I'm trying to do that:
public static List<Category> getCategories() {
try {
return new Select()
.all()
.from(Category.class)
.orderBy("NumInRow ASC") // NumInRow is my int field
.execute();
} catch (Exception ignored) {
return null;
}
}
Am I right?
Yes Absolutely ,what you have done is Correct way to order the column,it doesn't matter whether it is a int or some other data type.
Example :
public static List<Item> getAll(Category category) {
// This is how you execute a query
return new Select()
.from(Item.class)
.where("Category = ?", category.getId())
.orderBy("Name ASC")
.execute();
}
Active Android Complete Guide
Using Active Android

OrmLite execute sql statement

I have a database in OrmLite.
Here one of the tables — Field:
#DatabaseTable
public class Field {
#DatabaseField(generatedId = true)
private long id;
#DatabaseField
private String type;
#ForeignCollectionField(eager = true)
private Collection<FieldListValue> listValue;
...
}
I want to delete some values from the table like in this way:
List<Field> fields = fieldDao.queryForAll();
for (Field field : fields) {
if (field.getType().equals("list") && field.getListValue().size() == 0) {
fieldDao.delete(field);
}
}
But how can I execute this query with DeleteBuilder ?
The problem with this piece of code ...(SELECT COUNT(listValue) FROM Field) = 0
But how can I execute this query with DeleteBuilder ?
There is not a direct way that you can use the DeleteBuilder to do this because the foreign objects actually have no information in the Field class.
However, here's one way you can accomplish this using a raw-query and then the DeleteBuilder.
In approximate code:
qb = fieldListValueDao.queryBuilder();
// raw query for the field_ids in the fieldListValue table
rawResults = qb.queryRaw("SELECT field_id FROM fieldListValue GROUP BY field_id",
new RawRowMapper<Integer>() {
// each result row is a single integer in the 0th column
public Integer mapRow(String[] columnNames, String[] resultColumns) {
return Integer.parseInt(resultColumns[0]);
}
});
For help on the raw queries see: http://ormlite.com/docs/raw-queries
Once you have the raw-results of the field_id values, you can then do:
deleteBuilder = fieldDao.deleteBuilder();
// delete any rows that are not in the raw-results -- who have no fieldListValue entries
deleteBuilder.where().notIn("id", rawResults);
deleteBuilder.delete();
You also might be able to do it with the notIn("id", queryBuilder) method:
qb = fieldListValueDao.queryBuilder();
qb.selectColumns("field_id");
qb.groupBy("field_id");
...
deleteBuilder = fieldDao.deleteBuilder();
deleteBuilder.where().notIn("id", qb);
deleteBuilder.delete();
I would need to check this to make sure however.
Hope this helps.
You can do it this way
//get instance of DeleteBuilder
DeleteBuilder<Field, Integer> deleteBuilder = fieldDao.deleteBuilder();
//construct yours WHERE
//in this exampe we select fields with "id"=0
deleteBuilder.where().eq("id", 0);
//call delete
deleteBuilder.delete();
If you want to delete rows, that you want after yours codes conditions you can form an ArrayList of objects to delete and then pass their ids to deleteBuilder where statement like so
List<Integer> ids= new ArrayList<Integer>();
List<Field> fields = fieldDao.queryForAll();
List<Field> fieldsToDelete = new ArrayList<Field>();
for (Field field : fields)
{
if (field.getType().equals("list") && field.getListValue().size() == 0)
{
ids.add(field.getId);
fieldsToDelete.add(field);
}
}
fieldDao.delete(ids);
//or
fieldDao.delete(fieldsToDelete);
//or
//get instance of DeleteBuilder
DeleteBuilder<Field, Integer> deleteBuilder = fieldDao.deleteBuilder();
//construct yours WHERE
//in this exampe we select fields with "id"=0
deleteBuilder.where().in("id", ids);
//call delete
deleteBuilder.delete();

use cursor to query from google app engine in android

Ive tried a thousand things. As of right now the only way for me to query anything is to get the entire list and look through it that way! which takes way to much time. How can I query something in google app engine, for example pull only the entities that have > 100 votes for example.
Tried to user cursor but not sure how it works. I know it can use a cursor but how do I set it up with google app engine since my database isnt in my app per say??
Ive tried... but this dose not work at all..
Cursor cursor = ("select * from Votes WHERE Votes >" + 250 , null);
quotes endpoint.listquotes().setCursor(cursor).execute();
and
String query = ("select * from Votes WHERE Votes >= 40");
quotes endpoint.listquotes().setCursor(query).execute();
Im following the tic-tac-toe example https://github.com/GoogleCloudPlatform/appengine-endpoints-tictactoe-java and https://developers.google.com/eclipse/docs/endpoints-addentities In the example I just switched notes for quotes.
Heres my current code for example on how im getting the entities.
protected CollectionResponseQuotes doInBackground(Context... contexts) {
Quotesendpoint.Builder endpointBuilder = new Quotesendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(),
new HttpRequestInitializer() {
public void initialize(HttpRequest httpRequest) { }
});
Quotesendpoint endpoint = CloudEndpointUtils.updateBuilder(
endpointBuilder).build();
try {
quotes = endpoint.listquotes().execute();
for (Quotes quote : quotes.getItems()) {
if (quote.getVotes() > 3) {
quoteList.add(quote);
}
}
Here is the code that Google generated in the app engine for me when I created the endpoint. It looks like it will query somehow but I cant figure it out. They are two different projects.
#Api(name = "quotesendpoint", namespace = #ApiNamespace(ownerDomain = "projectquotes.com" ownerName = "projectquotes.com", packagePath = ""))
public class quotesEndpoint {
/**
* This method lists all the entities inserted in datastore.
* It uses HTTP GET method and paging support.
*
* #return A CollectionResponse class containing the list of all entities
* persisted and a cursor to the next page.
*/
#SuppressWarnings({ "unchecked", "unused" })
#ApiMethod(name = "listquotes")
public CollectionResponse<quotes> listquotes(
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit) {
EntityManager mgr = null;
Cursor cursor = null;
List<quotes> execute = null;
try {
mgr = getEntityManager();
Query query = mgr.createQuery("select from quotes as quotes");
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
if (limit != null) {
query.setFirstResult(0);
query.setMaxResults(limit);
}
execute = (List<quotes>) query.getResultList();
cursor = JPACursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (quotes obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<quotes> builder().setItems(execute)
.setNextPageToken(cursorString).build();
In Google App Engine you need to set up a servlet to query the database for you and then return the results in JSON, see here for more information:
https://developers.google.com/appengine/docs/java/datastore/queries
https://github.com/octo-online/robospice
https://developers.google.com/appengine/docs/java/#Requests_and_Servlets
https://code.google.com/p/google-gson/
You would end up querying using http:// your-url/query? + query string
EDIT:
Preview!
This is a Preview release of Google Cloud Endpoints. As a result, the
API is subject to change and the service itself is currently not
covered by any SLA or deprecation policy. These characteristics will
be evaluated as the API and service moves towards General
Availability, but developers should take this into consideration when
using the Preview release of Google Cloud Endpoints.
Most likely the cursor function is still in development. But I'm also unsure why you would want to use Cursors, as Collections are so much easier to work with... Wouldn't you prefer to do what's below then the awful code above? :)
ScoreCollection scores = service.scores().list().execute();
Update your list method to take in a filter attribute
#SuppressWarnings({ "unchecked", "unused" })
#ApiMethod(name = "listZeppaUserInfo")
public CollectionResponse<ZeppaUserInfo> listZeppaUserInfo(
#Nullable #Named("filter") String filterString,
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit) {
PersistenceManager mgr = null;
Cursor cursor = null;
List<ZeppaUserInfo> execute = null;
try {
mgr = getPersistenceManager();
Query query = mgr.newQuery(ZeppaUserInfo.class);
if (isWebSafe(cursorString)) {
cursor = Cursor.fromWebSafeString(cursorString);
HashMap<String, Object> extensionMap = new HashMap<String, Object>();
extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
query.setExtensions(extensionMap);
} else if (isWebSafe(filterString)){
// query has a filter
query.setFilter(filterString);
}
if (limit != null) {
query.setRange(0, limit);
}
execute = (List<ZeppaUserInfo>) query.execute();
cursor = JDOCursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and
// accomodate
// for lazy fetch.
for (ZeppaUserInfo obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<ZeppaUserInfo> builder().setItems(execute)
.setNextPageToken(cursorString).build();
}

How to store data from SQLite in a 2D Arraylist?

I need to get all of the information from my SQLite Database and store it in an Array List, or some other way if there is a better way. My database has 6 columns, here is how I am attempting to extract the data and store it in an Arraylist index;
db.open();
for(int i = 0; i<= amount; i++)
{
Cursor c = db.fetchAllNotes();
if (c.moveToFirst())
{
do {
mid = c.getString(0);
place =c.getString(1);
info =c.getString(2);
coordl1 =c.getString(3);
coordl2 =c.getString(4);
colour =c.getString(5);
//code here to store each string in an Array index
mapSetupList.add(mid,place,info,coordl1,coordl2,colour);
}while (c.moveToNext());
}
}
db.close();
I know how to create an Array list, but I do not know how to store 6 strings in one index, I experimented with 2D Arraylists, but this seemed to be too complicated and I didn't think it was the right way to do it. Is there a better way to do this, if not how can this be done with Arraylists?
What about to create one own defined Object that will wrap all columns as properties?
public class Foo {
private int id; // alternative to id column in db
private String type;
private String date;
...
public void setId(int id) { // setter
this.id = id;
}
public int getId() { // getter
return this.id;
}
}
Then create ArrayList<Foo> and now you can simply save data from SQLite into ArrayList:
public void store() {
Cursor c = null; // first declare and initialise appropriate objects
ArrayList<Foo> foos = new ArrayList<Foo>();
Foo member = null;
try {
c = db.rawQuery(query, whereArgs); // perform query
if (c.moveToFirst()) { // move cursor to first row because implicitly
do { // cursor is position before first row
member = new Foo(); // for each row create new Foo
member.setId(c.getInt(0)); // initialise properties
member.setType(c.getString(1));
member.setDate(c.getString(2));
...
foos.add(member); // add Foo into ArrayList
} while (c.moveToNext()); // it moves cursor to next row
}
}
finally { // in finally block release datasource(s), cursor(s)
if (c != null) {
c.close();
}
if (db != null && db.isOpen()) {
db.close();
}
}
}
Note: I recommend this approach. It's clear, safe and effective. Don't forget to release any datasources, cursors after work is done to avoid usually thrown exceptions like cursor is already open, database is already closed etc.
Update:
I am unsure about the class example, with the defined object and
getters and setters, can you please elaborate before I try this? Thank
you!!
So getters and setters are methods which are used "generaly "for manipulating with properies of Object to preserve Encapsulation - very important thing in OOP. Setters are used for initialising properties and getters for getting properties of Object.
Now i wrote for you example of method for store data from sqlite into ArrayList. There is this line:
member.setId(c.getInt(0));
where setId(c.getInt(0)) is setter of Foo Object with one Integer as parameter and with this method now you will fill up id value with data from Cursor.
Create a Class that contains all the informations that you like, and then create an instance of it then add that instance to the ArrayList.

Categories

Resources