i want to make a simple query, with multiple conditions
I use OrmLite to map entity object.
Now I want to search for an object into my table.
Supposing i have a Person entity that maps PERSON table, what I want to do is to initialize an object with some parameters and search it.
Suppose a function searchPerson(Person oPerson)
If i pass an object OPerson like this
Id = null
Name = John
Age = null
Sex = male
Is possible to write a query to reach that goal? Something like this pseudo-code
pers = (from p in db.Table<Person>()
where (if OPerson.Id !=null) p.Id==OPerson.Id}
AND {(if OPerson.Name !=null) p.Name.Contains(OPerson.Name)}
AND {(if condition) where-contion}
select p).ToList();
I know that i can do multiple query in this way
list=PersonDao.queryBuilder().where().eq("name",OPerson.name)
.and().eq("sex",OPerson.sex").query();
but I want also to check if the value exists
where (if OPerson.Id !=null) p.Id==OPerson.Id}
#ArghArgh is close but doesn't have the ANDs right. The problem is that the AND statements are conditional on whether there were any previous statements. I'd do something like:
QueryBuilder<Person, Integer> queryBuilder = dao.queryBuilder();
Where<Person, Integer> where = queryBuilder.where();
int condCount = 0;
if (oPerson.id != null) {
where.eq("id", oPerson.id);
condCount++;
}
if (oPerson.name != null) {
where.like("name", "%" + oPerson.name + "%");
condCount++;
}
...
// if we've added any conditions then and them all together
if (condCount > 0) {
where.and(condCount);
}
// do the query
List<Persion> personList = queryBuilder.query();
This makes use of the where.and(int) method which takes a number of clauses on the stack and puts them together with ANDs between.
I think that you must use the QueryBuilder.
Try something like this
QueryBuilder<Person, Integer> queryBuilder = PersonDao.queryBuilder();
// get the WHERE object to build our query
Where<Person, String> where = queryBuilder.where();
if(oPerson.Name!=null)
where.like("Name", "%"+oPerson.Name+"%");
// and
where.and();
if(Person.Sex!=null)
where.like("Sex", "%"+oPerson.sex+"%");
PreparedQuery<Person> preparedQuery = queryBuilder.prepare();
Than you can call it in this way
List<Person> list = PersontDao.query(preparedQuery);
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.
I have these tables in an Android based application where I'm using OrmLite for the database management.
What I want to have an x number of array list depending on how many of the product type FOLDER I have.
So in this case I want to a list of products where the productId equals parentId.
So I want a list where
if(productType = FOLDER) {
if(productId = parentId){
//add product
}
}
Basically what I want to end up with, in this case three lists with each containing a list of products where parentId is the same for every product.
I've tried many things, and some works better than others, but a code I want to run actually throws a nullpointer.
DatabaseHelper dbHelper = getHelper();
List<Product> productsParents = null;
try {
Dao<Product, Integer> dao = dbHelper.getDao();
PreparedQuery<Product> prepQu = dao.queryBuilder().where()
.eq("parentId", dao.queryBuilder().selectColumns("productId").where()
.eq("productType", ProductType.FOLDER).prepare()).prepare();
productsParents = dao.query(prepQu);
} catch (SQLException e) {
...
}
This code isn't working because productParents returns null, and it does not do what I want, even though it's a slight hint. If someone know how to do this in code that would be sufficient also, or more likely a mix of java and ormlite.
Have you had a chance to RTFM around building queries? The ORMLite docs are pretty extensive:
http://ormlite.com/docs/query-builder
Your problem is that a prepared query cannot be an argument to the eq(...) method. Not sure where you saw an example of that form.
So there are a couple ways you can do this. The easiest way is to do a different query for each productType:
Where<Product, Integer> where = dao.queryBuilder().where();
where.eq("parentId", parentId).and().eq("productType", ProductType.FOLDER);
productsParents = where.query();
// then do another similar query again with ProductType.PRODUCT, ...
If you want to do just one query then you can get all products that match the parentId and then separate them using code:
Where<Product, Integer> where = dao.queryBuilder().where();
where.eq("parentId", parentId);
productsParents = where.query();
List<Product> productFolders = new ArrayList<Product>();
List<Product> productProducts = new ArrayList<Product>();
...
for (Product product : productsParents) {
if (product.getProductType() == ProductType.FOLDER) {
productFolders.add(product);
} else if (product.getProductType() == ProductType.PRODUCT) {
productProducts.add(product);
} else ...
}
I'm tring to make join in two tables and get all columns in both, I did this:
QueryBuilder<A, Integer> aQb = aDao.queryBuilder();
QueryBuilder<B, Integer> bQb = bDao.queryBuilder();
aQb.join(bQb).prepare();
This equates to:
SELECT 'A'.* FROM A INNER JOIN B WHERE A.id = B.id;
But I want:
SELECT * FROM A INNER JOIN B WHERE A.id = B.id;
Other problem is when taking order by a field of B, like:
aQb.orderBy(B.COLUMN, true);
I get an error saying "no table column B".
When you are using the QueryBuilder, it is expecting to return B objects. They cannot contain all of the fields from A in B. It will not flesh out foreign sub-fields if that is what you mean. That feature has not crossed the lite barrier for ORMLite.
Ordering on join-table is also not supported. You can certainly add the bQb.orderBy(B.COLUMN, true) but I don't think that will do what you want.
You can certainly use raw-queries for this although it is not optimal.
Actually, I managed to do it without writing my whole query as raw query. This way, I didn't need to replace my query builder codes (which is pretty complicated). To achieve that, I followed the following steps:
(Assuming I have two tables, my_table and my_join_table and their daos, I want to order my query on my_table by the column order_column_1 of the my_join_table)
1- Joined two query builders & used QueryBuilder.selectRaw(String... columns) method to include the original table's + the columns I want to use in foreign sort. Example:
QueryBuilder<MyJoinTable, MyJoinPK> myJoinQueryBuilder = myJoinDao.queryBuilder();
QueryBuilder<MyTable, MyPK> myQueryBuilder = myDao.queryBuilder().join(myJoinQueryBuilder).selectRaw("`my_table`.*", "`my_join_table`.`order_column` as `order_column_1`");
2- Included my order by clauses like this:
myQueryBuilder.orderByRaw("`order_column_1` ASC");
3- After setting all the select columns & order by clauses, it's time to prepare the statement:
String statement = myQueryBuilder.prepare().getStatement();
4- Get the table info from the dao:
TableInfo tableInfo = ((BaseDaoImpl) myDao).getTableInfo();
5- Created my custom column-to-object mapper which just ignores the unknown column names. We avoid the mapping error of our custon columns (order_column_1 in this case) by doing this. Example:
RawRowMapper<MyTable> mapper = new UnknownColumnIgnoringGenericRowMapper<>(tableInfo);
6- Query the table for the results:
GenericRawResults<MyTable> results = activityDao.queryRaw(statement, mapper);
7- Finally, convert the generic raw results to list:
List<MyTable> myObjects = new ArrayList<>();
for (MyTable myObject : results) {
myObjects.add(myObject);
}
Here's the custom row mapper I created by modifying (just swallowed the exception) com.j256.ormlite.stmt.RawRowMapperImpl to avoid the unknown column mapping errors. You can copy&paste this into your project:
import com.j256.ormlite.dao.RawRowMapper;
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.table.TableInfo;
import java.sql.SQLException;
public class UnknownColumnIgnoringGenericRowMapper<T, ID> implements RawRowMapper<T> {
private final TableInfo<T, ID> tableInfo;
public UnknownColumnIgnoringGenericRowMapper(TableInfo<T, ID> tableInfo) {
this.tableInfo = tableInfo;
}
public T mapRow(String[] columnNames, String[] resultColumns) throws SQLException {
// create our object
T rowObj = tableInfo.createObject();
for (int i = 0; i < columnNames.length; i++) {
// sanity check, prolly will never happen but let's be careful out there
if (i >= resultColumns.length) {
continue;
}
try {
// run through and convert each field
FieldType fieldType = tableInfo.getFieldTypeByColumnName(columnNames[i]);
Object fieldObj = fieldType.convertStringToJavaField(resultColumns[i], i);
// assign it to the row object
fieldType.assignField(rowObj, fieldObj, false, null);
} catch (IllegalArgumentException e) {
// log this or do whatever you want
}
}
return rowObj;
}
}
It's pretty hacky & seems like overkill for this operation but I definitely needed it and this method worked well.
I have two tables CustomerBalance and Customer which are bound with CustomerRefId field.
I want the CustomerBalance records that are lets say greater than 100 for a field balance of this tables. I also want to include into my results the name of the particular customer that fulfills that criteria. I created the following method that works!
public List<CustomerBalance> getCustomerBalanceFilter(String filterVal) {
try {
PreparedQuery<CustomerBalance> preparedQuery = mDbHelper.getCustomerBalanceDao().queryBuilder()
.where().gt(CustomerBalance.DB_COL_CUSTOMER_BALANCE, filterVal)
.prepare();
List<CustomerBalance> result = mDbHelper.getCustomerBalanceDao().query(preparedQuery);
for(CustomerBalance alert : result) {
PreparedQuery<Customer> getCustQuery = mDbHelper.getCustomerDao().queryBuilder()
.where().eq(Customer.DB_COL_CUSTOMER_REF_ID, alert.getCustomerID())
.prepare();
List<Customer> customer = mDbHelper.getCustomerDao().query(getCustQuery);
alert.setCustomer(customer.size() == 1 ? customer.get(0) : null);
}
return result;
} catch(Exception ex) {
return null;
}
}
This methods is working, is this the best way to write such a query? or is there a more appropriate approach?
One improvement to your query is to use ORMLite's SelectArg to pass in the customer-id instead of a new query each time. Something like:
...
List<CustomerBalance> result = mDbHelper.getCustomerBalanceDao()
.query(preparedQuery);
SelectArg custIdArg = new SelectArg();
PreparedQuery<Customer> getCustQuery = mDbHelper.getCustomerDao().queryBuilder()
.where().eq(Customer.DB_COL_CUSTOMER_REF_ID, custIdArg)
.prepare();
for (CustomerBalance alert : result) {
custIdArg.setValue(alert.getCustomerID());
List<Customer> customer = mDbHelper.getCustomerDao().query(getCustQuery);
alert.setCustomer(customer.size() == 1 ? customer.get(0) : null);
}
Here are the docs for SelectArg:
http://ormlite.com/docs/select-arg
FYI, there also is an UpdateBuilder, but I don't see an easy way to turn your code above into a single UPDATE statement.