I have this method:
public String givenCheckmark(String name, String date)
{
SQLiteDatabase db = Cache.openDatabase();
Cursor cursor = db.rawQuery("select value from checkmarks where timestamp ='"+date+"' and habit ='"+name+"'", null);
String habitValue = "";
cursor.moveToFirst();
if (!(cursor == null)) {
habitValue = Integer.toString(cursor.getInt(0));
}
cursor.close();
return habitValue;
}
for some reason if i delete the
habitValue = Integer.toString(cursor.getInt(0));
the app does not crash. so the problem must be in the cursor.getInt(0). The query returns only one line. I am guessing the cursor is not in the first line but...why??
The most likely reason is the item at index "0" is not an Integer. Another reason is the Cursor itself may be empty. Finally, you probably have to check if there is actually a value returned.
To address the first part, you need to use Cursor#getColumnIndex() to get the index of the column you're trying to retrieve. So if it's an "id" you want, then you would do:
int id = cursor.getInt(cursor.getColumnIndex("id"));
To address the second part, you need to ensure that there were results returned. To do that, you just check Cursor#getCount(). So:
boolean isEmpty = cursor.getCount() == 0;
Alternatively, the return value for Cursor#moveToFirst() will actually return false if the cursor is empty meaning you can retrieve values by using something like this:
if (cursor != null && cursor.moveToFirst()) {
// The cursor is not null and contains elements. Continue retrieving values.
}
For the third part, you can use Cursor#isNull() to check if there is a value at the given index. So something like this:
boolean doesNotHaveValue = cursor.isNull(cursor.getColumnIndex("id"));
Other problems I see here is you're checking if the cursor is null after you move it to the first index meaning that you'll get a NullPointerException regardless of wether or not the cursor was null. You're also closing the cursor regardless of whether or not it is null.
I am unable to figure out some small issue that is there in my code. I am having a method that is returning multiple flags from a stored procedure.
Here is my code:
// QueryDataSet qds;
Object[] flags = null;
flags = (Call to a stored procedure that is returning multiple result sets)
if(flags != null)
{
for(int i = 0; i < flags.length; i++)
{
qds = ((QueryDataSet)flags[i]);
if(qds != null)
{
int result = qds.getRecord(0).getValue(1).asInt();
if(result>0) booleanflags[i]=true;
}
}
}
// getValue implementation is returning type of Record and getValue takes in the columnIndex. The stored procedure is returning multiple records and only one column and I am trying to check the count. If greater that 1 then return true else false.
// I am using the debugger and see that the first time in the loop the value is returned fine but when i=1 then it returns Invalid cursor position.
Given an instance of Query is it possible to somehow check whether that instance happens to represent a query that always matches all the documents in the index?
For example, a MatchAllDocsQuery or a BooleanQuery that contains a MatchAllDocs clause are such queries that always return all the documents. Another example is a BooleanQuery that has a SHOULD-match clause that has a nested SHOULD-match clause that has a MatchAllDocs inside it.
Note that a query that happens to return everything because it has all the possible terms in it or because the index is empty doesn't count as a query that always return all the documents. In other words, I would like to check whether a given query always returns everything no matter what the index contains.
Is it possible or at least approximately possible? I'll accept an answer with a solution that doesn't work for any conceivable case if it works for any query that can be returned from Solr's Extended Dismax Query Parser.
A BooleanQuery that contains a MatchAllDocsQuery as one of it's clauses doesn't necessarily return all documents, as the BooleanQuery may also contain other MUST or MUST_NOT clauses which would restrict the result set. I don't believe there is anything the does this out of the box, and trying to handle any sort of query that Solr might split out would be difficult. You would need to move through the queries recursively to ensure that everything effectively reduces to a MatchAllDocsQuery, ignoring scores.
Something like (this is entirely untested at this point):
boolean willMatchAll(Query query) {
if (query instanceof MatchAllDocsQuery)
return true;
}
else if (query instanceof BooleanQuery) {
boolean foundMatchAll = false;
for (BooleanClause clause : ((BooleanQuery)query).getClauses()) {
if (clause.isProhibited()) {
return false; //A reasonable assumption, that the MUST_NOT clauses won't be empty
}
else if (clause.isRequired()) {
if (willMatchAll(clause.getQuery())) {
foundMatchAll = true;
} else {
return false; //any MUST clause that is not a matchall means the boolean query will not match all
}
}
else {
if (willMatchAll(clause.getQuery())) {
foundMatchAll = true;
}
}
}
//If a matchall has been found, and we haven't return false yet, this boolean query matches all documents
return foundMatchAll;
}
else if (query instanceof DisjunctionMaxQuery) {
boolean isMatchAll = false
//If any disjunct is a matchall, the query will match all documents
for (Query subquery : ((DisjunctuionMaxQuery)query).getDisjuncts()) {
isMatchAll = isMatchAll || willMatchAll(subquery);
}
return isMatchAll;
}
else if (query instanceof ConstantScoreQuery) {
//Traverse right through ConstantScoreQuery. The wrapper isn't of interest here.
Query subquery = ((ConstantScoreQuery)query).getQuery()
if (subquery == null) {
return false; //It wraps a filter, not a query, and I don't believe a filter can be a matchall
}
return willMatchAll(subquery);
}
else {
//No other standard queries may be or contain MatchAllDocsQueries, I don't believe.
//Even a double open-ended range query restricts the results to those with a value in the specified field.
return false;
}
}
And if you also wanted to handle the stuff in org.apache.lucene.queries, there would be more query types to handle, like BoostingQuery and CustomScoreQuery, among others. But hopefully that gives some sort of idea on it.
Good question, i am wondering if you can do : search and get numFound and compare that to see if your actual Query returns same numFound value. Am i missing something?
The below code functions, but Hibernate never lets go of its grip of any object. Calling session.clear() causes exceptions regarding fetching a joined class, and calling session.evict(currentObject) before retrieving the next object also fails to free the memory. Eventually I exhaust my heap space.
Checking my heap dumps, StatefulPersistenceContext is the garbage collector's root for all references pointing to my objects.
public class CriteriaReportSource implements JRDataSource {
private ScrollableResults sr;
private Object currentObject;
private Criteria c;
private static final int scrollSize = 10;
private int offset = 1;
public CriteriaReportSource(Criteria c) {
this.c = c;
advanceScroll();
}
private void advanceScroll() {
// ((Session) Main.em.getDelegate()).clear();
this.sr = c.setFirstResult(offset)
.setMaxResults(scrollSize)
.scroll(ScrollMode.FORWARD_ONLY);
offset += scrollSize;
}
public boolean next() {
if (sr.next()) {
currentObject = sr.get(0);
if (sr.isLast()) {
advanceScroll();
}
return true;
}
return false;
}
public Object getFieldValue(JRField jrf) throws JRException {
Object retVal = null;
if(currentObject == null) { return null; }
try {
retVal = PropertyUtils.getProperty(currentObject, jrf.getName());
} catch (Exception ex) {
Logger.getLogger(CriteriaReportSource.class.getName()).log(Level.SEVERE, null, ex);
}
return retVal;
}
}
Don't use the stateful session here, it's just NOT the right tool to walk millions of rows and build a report. Use The StatelessSession interface instead.
If using MySQL Connector/J even that is not enough, you need to also defeat the internal buffering done by the JDBC driver, with this:
Query query = session.createQuery(query);
query.setReadOnly(true);
// MIN_VALUE gives hint to JDBC driver to stream results
query.setFetchSize(Integer.MIN_VALUE);
ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
// iterate over results
while (results.next()) {
Object row = results.get();
// process row then release reference
// you may need to evict() as well
}
results.close();
Couple of things I would suggest:
Try calling setCacheMode(CacheMode.IGNORE) on the Criteria before opening it.
In the advanceScroll() method, add if (sr != null) sr.close(); so that the previous ScrollableResults gets closed before you do the re-assignment to the new one.
One question: What is the reason for calling setMaxSize(), and then keeping track of the offset and then re-opening the scrollable results, why not just do this?
public CriteriaReportSource(Criteria c) {
this.c = c;
this.sr = c.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
}
public boolean next() {
if (sr.next()) {
currentObject = sr.get(0);
return true;
}
return false;
}
I think one of my problems was that
if (sr.isLast()) {
advanceScroll();
//...
combined with
((Session) Main.em.getDelegate()).clear();
//Also, "Main.em.clear()" should do...
resulted in flushing the database out one run too early. That was the cause of exceptions regarding collections. Collections cannot be handled in a StatelessSession, so that's off the table. I don't know why session.evict(currentObject) fails to work when Session.clear() does work, but that's the way I'll have to handle it for now. I'll toss the answer points to whoever can figure that one out.
So, for now, there we have an answer. A manual scrolling window is required, closing the ScrollableResults doesn't help, and I need to properly run a Session.clear().
I have an insertOrUpdate method which inserts an Entity when it doesn't exist or update it if it does. To enable this, I have to findByIdAndForeignKey, if it returned null insert if not then update. The problem is how do I check if it exists? So I tried getSingleResult. But it throws an exception if the
public Profile findByUserNameAndPropertyName(String userName, String propertyName) {
String namedQuery = Profile.class.getSimpleName() + ".findByUserNameAndPropertyName";
Query query = entityManager.createNamedQuery(namedQuery);
query.setParameter("name", userName);
query.setParameter("propName", propertyName);
Object result = query.getSingleResult();
if (result == null) return null;
return (Profile) result;
}
but getSingleResult throws an Exception.
Thanks
Throwing an exception is how getSingleResult() indicates it can't be found. Personally I can't stand this kind of API. It forces spurious exception handling for no real benefit. You just have to wrap the code in a try-catch block.
Alternatively you can query for a list and see if its empty. That doesn't throw an exception. Actually since you're not doing a primary key lookup technically there could be multiple results (even if one, both or the combination of your foreign keys or constraints makes this impossible in practice) so this is probably the more appropriate solution.
Try this in Java 8:
Optional first = query.getResultList().stream().findFirst();
I encapsulated the logic in the following helper method.
public class JpaResultHelper {
public static Object getSingleResultOrNull(Query query){
List results = query.getResultList();
if (results.isEmpty()) return null;
else if (results.size() == 1) return results.get(0);
throw new NonUniqueResultException();
}
}
Here's a good option for doing this:
public static <T> T getSingleResult(TypedQuery<T> query) {
query.setMaxResults(1);
List<T> list = query.getResultList();
if (list == null || list.isEmpty()) {
return null;
}
return list.get(0);
}
I've done (in Java 8):
query.getResultList().stream().findFirst().orElse(null);
From JPA 2.2, instead of .getResultList() and checking if list is empty or creating a stream you can return stream and take first element.
.getResultStream()
.findFirst()
.orElse(null);
Spring has a utility method for this:
TypedQuery<Profile> query = em.createNamedQuery(namedQuery, Profile.class);
...
return org.springframework.dao.support.DataAccessUtils.singleResult(query.getResultList());
If you wish to use the try/catch mechanism to handle this problem.. then it can be used to act like if/else. I used the try/catch to add a new record when I didn't find an existing one.
try { //if part
record = query.getSingleResult();
//use the record from the fetched result.
}
catch(NoResultException e){ //else part
//create a new record.
record = new Record();
//.........
entityManager.persist(record);
}
Here's a typed/generics version, based on Rodrigo IronMan's implementation:
public static <T> T getSingleResultOrNull(TypedQuery<T> query) {
query.setMaxResults(1);
List<T> list = query.getResultList();
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
There is an alternative which I would recommend:
Query query = em.createQuery("your query");
List<Element> elementList = query.getResultList();
return CollectionUtils.isEmpty(elementList ) ? null : elementList.get(0);
This safeguards against Null Pointer Exception, guarantees only 1 result is returned.
So don't do that!
You have two options:
Run a selection to obtain the COUNT of your result set, and only pull in the data if this count is non-zero; or
Use the other kind of query (that gets a result set) and check if it has 0 or more results. It should have 1, so pull that out of your result collection and you're done.
I'd go with the second suggestion, in agreement with Cletus. It gives better performance than (potentially) 2 queries. Also less work.
Combining the useful bits of the existing answers (limiting the number of results, checking that the result is unique) and using the estabilshed method name (Hibernate), we get:
/**
* Return a single instance that matches the query, or null if the query returns no results.
*
* #param query query (required)
* #param <T> result record type
* #return record or null
*/
public static <T> T uniqueResult(#NotNull TypedQuery<T> query) {
List<T> results = query.setMaxResults(2).getResultList();
if (results.size() > 1) throw new NonUniqueResultException();
return results.isEmpty() ? null : results.get(0);
}
The undocumented method uniqueResultOptional in org.hibernate.query.Query should do the trick. Instead of having to catch a NoResultException you can just call query.uniqueResultOptional().orElse(null).
I solved this by using List<?> myList = query.getResultList(); and checking if myList.size() equals to zero.
Look this code :
return query.getResultList().stream().findFirst().orElse(null);
When findFirst() is called maybe can be throwed a NullPointerException.
the best aproach is:
return query.getResultList().stream().filter(Objects::nonNull).findFirst().orElse(null);
Here's the same logic as others suggested (get the resultList, return its only element or null), using Google Guava and a TypedQuery.
public static <T> getSingleResultOrNull(final TypedQuery<T> query) {
return Iterables.getOnlyElement(query.getResultList(), null);
}
Note that Guava will return the unintuitive IllegalArgumentException if the result set has more than one result. (The exception makes sense to clients of getOnlyElement(), as it takes the result list as its argument, but is less understandable to clients of getSingleResultOrNull().)
Here's another extension, this time in Scala.
customerQuery.getSingleOrNone match {
case Some(c) => // ...
case None => // ...
}
With this pimp:
import javax.persistence.{NonUniqueResultException, TypedQuery}
import scala.collection.JavaConversions._
object Implicits {
class RichTypedQuery[T](q: TypedQuery[T]) {
def getSingleOrNone : Option[T] = {
val results = q.setMaxResults(2).getResultList
if (results.isEmpty)
None
else if (results.size == 1)
Some(results.head)
else
throw new NonUniqueResultException()
}
}
implicit def query2RichQuery[T](q: TypedQuery[T]) = new RichTypedQuery[T](q)
}
So all of the "try to rewrite without an exception" solution in this page has a minor problem. Either its not throwing NonUnique exception, nor throw it in some wrong cases too (see below).
I think the proper solution is (maybe) this:
public static <L> L getSingleResultOrNull(TypedQuery<L> query) {
List<L> results = query.getResultList();
L foundEntity = null;
if(!results.isEmpty()) {
foundEntity = results.get(0);
}
if(results.size() > 1) {
for(L result : results) {
if(result != foundEntity) {
throw new NonUniqueResultException();
}
}
}
return foundEntity;
}
Its returning with null if there is 0 element in the list, returning nonunique if there are different elements in the list, but not returning nonunique when one of your select is not properly designed and returns the same object more then one times.
Feel free to comment.
I achieved this by getting a result list then checking if it is empty
public boolean exist(String value) {
List<Object> options = getEntityManager().createNamedQuery("AppUsers.findByEmail").setParameter('email', value).getResultList();
return !options.isEmpty();
}
It is so annoying that getSingleResult() throws exceptions
Throws:
NoResultException - if there is no result
NonUniqueResultException - if more than one result
and some other exception that you can get more info on from their documentation
I prefer #Serafins answer if you can use the new JPA features, but this is one fairly straight forward way to do it which I'm surprised hasn't been mentioned here before:
try {
return (Profile) query.getSingleResult();
} catch (NoResultException ignore) {
return null;
}
`public Example validate(String param1) {
// TODO Auto-generated method stub
Example example = new Example();
Query query =null;
Object[] myResult =null;
try {
query = sessionFactory.getCurrentSession()
.createQuery("select column from table where
column=:p_param1");
query.setParameter("p_param1",param1);
}
myResult = (Object[])query.getSingleResult();//As your problem occurs here where the query has no records it is throwing an exception
String obj1 = (String) myResult[0];
String obj2 = (String) myResult[1];
example.setobj1(ISSUtil.convertNullToSpace(obj1))
example.setobj2(ISSUtil.convertNullToSpace(obj2));
return example;
}catch(Exception e) {
e.printStackTrace();
example.setobj1(ISSUtil.convertNullToSpace(""));//setting
objects to "" in exception block
example.setobj1(ISSUtil.convertNullToSpace(""));
}
return example;
}`
Answer : Obviously when there is no records getsingleresult will throw an exception i have handled it by setting the objects to "" in the exception block even though it enter the exception you JSON object will set to ""/empty
Hope this is not a perfect answer but it might help
If some needs to modify my code more precisely and correct me always welcome.
Thats works to me:
Optional<Object> opt = Optional.ofNullable(nativeQuery.getSingleResult());
return opt.isPresent() ? opt.get() : null;