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();
Related
I'm trying write a query using ORMLite. I need this query check a id of customer in other entity. How could I do it ?
Entities
#DatabaseTable(tableName = "customer")
public class Customer {
#DatabaseField(generatedId = true)
private Integer id;
#DatabaseField
private String name;
#DatabaseField
private Sale sale;
//gets sets
}
#DatabaseTable(tableName = "sale")
public class Sale{
#DatabaseField(generatedId = true)
private Integer id;
#DatabaseField
private Customer customer;
#DatabaseField
private Integer status;
//gets sets
}
Query
Customer customer = new Customer();
customer.setId(1);
customer.setName("Fernando Paiva");
QueryBuilder<Sale, Integer> qb = saleDAO.queryBuilder();
Where where = qb.where();
where.eq("sale.customer.id", customer.getId());
where.and();
where.eq("sale.status", 1);
PreparedQuery<Sale> pq = qb.prepare();
List<Sale> list = saleDAO.query(pq);
Log.i("SALE LIST->", list.size() + "");
You need to use JOIN
Here your example using Join:
First of all, you need a QueryBuilder to each Dao.
You can apply your filter to each QueryBuilder separately
Last but not least, you join the main QueryBuilder (Sales) with the Customer's QueryBuilder and
perform the query.
Here the code
Dao<Sale, Integer> saleDao = DaoManager.createDao(getConnectionSource(), Sale.class);
Dao<Customer, Integer> customerDao = DaoManager.createDao(getConnectionSource(), Customer.class);
QueryBuilder<Sale, Integer> saleQa= saleDao.queryBuilder();
saleQa.where().eq("status", 1);
QueryBuilder<Customer, Integer> customerQa = customerDao.queryBuilder();
customerQa.where().idEq(customer.getId());
sales = saleQa.join(customerQa).query();
Are you trying to use OrmLite to check if the customer id is the same as the sale id and get all of the matching result? If so the below code will do that
qb.where().eq("id", customer.id);
List<Sale> results = saleDAO.query(qb.prepare());
Update:
After rereading your question I realized what you're trying to do
qb.where().in(Sale.customer, id);
See this question for further details.
Ormlite Foreign Entity Searching
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.
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>();
}
Using ORMLite for Android, I need to build a query that returns orders by order id or by customer name. Please consider the following class declarations:
#DatabaseTable(tableName = "order")
public class Order {
#DatabaseField(generatedId = true)
private Long id;
#DatabaseField(foreign = true, canBeNull = false, foreignAutoRefresh = true, columnName = "customer_id")
private Customer customer;
// default constructor, getters and setters...
}
#DatabaseTable(tableName = "customer")
public class Customer {
#DatabaseField(generatedId = true)
private Long id;
#DatabaseField
private String name;
// default constructor, getters and setters...
}
The raw SQL I'm looking for would be something like this:
SELECT
o.*
FROM
order o
JOIN customer c on
o.customer_id = c.id
WHERE
(o.id = ?) OR (c.name = ?)
What is the best way to do this using ORMLite?
ORMLite now supports simple join queries.
So your query would look something like:
QueryBuilder<Customer, Integer> customerQb = customerDao.queryBuilder();
SelectArg nameSelectArg = new SelectArg();
// this gives the c.name = ?
customerQb.where().eq("name", nameSelectArg);
QueryBuilder<Account, Integer> orderQb = orderDao.queryBuilder();
SelectArg idSelectArg = new SelectArg();
// this gives the o.id = ?
orderQb.where().eq("id", idSelectArg);
orderQb.join(customerQb);
// then you set the args and run the query
nameSelectArg.setValue("jim");
idSelectArg.setValue(1);
List<Order> results = orderQb.join(customerQb).query();
No, JOINs are supported in ORMLite https://stackoverflow.com/a/7320091/323128
However, this reference will give a vision how to complete your task
I use ormlite and I have a db with a field:
public static final String NAME = "name";
#DatabaseField (canBeNull = false, dataType = DataType.SERIALIZABLE, columnName = NAME)
private String[] name = new String[2];
And I would like to get all elements that name[0] and name[1] are "car". I try to add a where clausule like:
NAMEDB nameDB = null;
Dao<NAMEDB, Integer> daoName = this.getHelper().getDao(NAMEDB.class);
QueryBuilder<NAMEDB, Integer> queryName = daoName.queryBuilder();
Where<NAMEDB, Integer> where = queryName.where();
where.in(nameDb.NAME, "car");
But it doesn't work because it's an array string.
I have other fields:
public static final String MARK = "mark";
#DatabaseField (canBeNull = false, foreign = true, index = true, columnName = MARK)
private String mark = null;
And I can do this:
whereArticulo.in(nameDB.MARK, "aaa");
How can I solve my problem? Thanks.
It seems to me that a third option to store a string array (String[] someStringArray[]) in the database using Ormlite would be to define a data persister class that converts the string array to a single delimited string upon storage into the database and back again to a string array after taking it out of the database.
E.g., persister class would convert ["John Doe", "Joe Smith"] to "John Doe | Joe Smith" for database storage (using whatever delimiter character makes sense for your data) and converts back the other way when taking the data out of the database.
Any thoughts on this approach versus using Serializable or a foreign collection? Anyone tried this?
I just wrote my first persister class and it was pretty easy. I haven't been able to identify through web search or StackOverflow search that anyone has tried this.
Thanks.
As ronbo4610 suggested, it is a good idea to use a custom data persister in this case, to store the array as a string in the database separated by some kind of delimiter. You can then search the string in your WHERE clause just as you would any other string. (For example, using the LIKE operator)
I have implemented such a data persister. In order to use it, you must add the following annotation above your String[] object in your persisted class:
#DatabaseField(persisterClass = ArrayPersister.class)
In addition, you must create a new class called "ArrayPersister" with the following code:
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.field.SqlType;
import com.j256.ormlite.field.types.StringType;
import org.apache.commons.lang3.StringUtils;
public class ArrayPersister extends StringType {
private static final String delimiter = ",";
private static final ArrayPersister singleTon = new ArrayPersister();
private ArrayPersister() {
super(SqlType.STRING, new Class<?>[]{ String[].class });
}
public static ArrayPersister getSingleton() {
return singleTon;
}
#Override
public Object javaToSqlArg(FieldType fieldType, Object javaObject) {
String[] array = (String[]) javaObject;
if (array == null) {
return null;
}
else {
return StringUtils.join(array, delimiter);
}
}
#Override
public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) {
String string = (String)sqlArg;
if (string == null) {
return null;
}
else {
return string.split(delimiter);
}
}
}
Unfortunately ORMLite does not support querying fields that are the type SERIALIZABLE. It is storing the array as a serialized byte[] so you cannot query against the values with an IN query like:
where.in(nameDb.NAME, "car");
ORMLite does support foreign collections but you have to set it up yourself with another class holding the names. See the documentation with sample code:
http://ormlite.com/docs/foreign-collection