Getting cursor with Objectify without iterating through items - java

I want to execute a query, get the results and then get the cursor to the next item if there is any. The only relevant post I found was: Objectify paging with Cursors
Is there a way of doing this without iterating through the items?
Query<User> query = ofy().load().type(User.class).limit(RecordLimit).filter("gameId", gameId);
//execute and get the results
List<User> users = query.list()
//get the cursor for the next user

String cursor = query.iterator().getCursor().toWebSafeString();
Look at these unit tests to make things a bit more clear.

Query is itself iterable - like a cursor.
You can directly do:
Query<User> query = blah;
for(User u: query) {
//u is next item from the "cursor"
}

Related

Java HQL Query on view does not map all the returned rows

I have a view in MySQL that joins a 1-* between Schemas and Properties.
The view works fine. When I run a query in MySQL workbench I get the expected results.
However, when I run the same query in my Java program using HQL, the expected number of rows are being returned, but only the 1st row has data in it. That first row is correct, content-wise.
My code is fairly straightforward (I hope...). Stepping through in debug I can see that queryResult.list has the right # rows that I would expect to be returned for the input objectIdentifier(of the schema), but only the first row has on object in it. The rest are empty. There should be one row for each joined property. As I say, the # of rows is correct.
public List<SchemaAndPropertiesResolvedNames> getSchemaAndPropertiesResolvedNamesView(
String schemaAndPropertiesResolvedNamesId, ServiceHeaderVO context)
throws DALException {
List<SchemaAndPropertiesResolvedNames> result = new ArrayList();
try{
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
String hql = "FROM SchemaAndPropertiesResolvedNames schemaandpropertiesresolvednames WHERE schemaandpropertiesresolvednames.objectIdentifier =:objectIdentifier";
Query queryResult = session.createQuery(hql);
queryResult.setParameter("objectIdentifier", schemaAndPropertiesResolvedNamesId);
List<SchemaAndPropertiesResolvedNames> listrows = queryResult.list();
Iterator iterator = listrows.iterator();
while (iterator.hasNext()) {
SchemaAndPropertiesResolvedNames obj = (SchemaAndPropertiesResolvedNames) iterator.next();
result.add(obj);
}
session.getTransaction().commit();
return result;
It appears to be partially working to the extent that it always has the correct number of rows in the queryResult (if I try different objectIdentifiers as input). It is just they are not populated apart from the first one.
Is the content of the view causing this?
The annoying this is I could have sworn it worked earlier. Then I went on to make other changes elsewhere, but when I tested it again it had this problem.
Any suggestions? This is the first time I have used HQL.

Bulk reading of data in hibernate using scrollable result set

I was reading a blog regarding bulk fetching with hibernate http://java.dzone.com/articles/bulk-fetching-hibernate.
In this, ScrollableResults is used as a solution. Here still we need to evict objects from session.
I don't understand how using ScrollableResults(or scroll()) is different from using list().
In other words, how the below statements differ in terms of performance
List<Employee> empList = session.createCriteria(Employee.class).list();
ScrollableResults sc = session.createCriteria(Employee.class).scroll();
Please let me know.
The above code seems to be missing some settings.
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 flush() as well
}
results.close();
Follow this link for more details and explanation.
I referred Hibernate API documentation to understand the difference between list() and scroll().
ScrollableResults is like a cursor . An important feature of ScrollableResults is that it allows accessing ith object in the current row of results, without initializing any other results in the row through get(int i) function.
It also allows moving back and forth the result set using next() and previous() function.
Example :
ScrollableResults sc = session.createQuery("select e.employeeName,e.employeeDept FROM Employee e").scroll(ScrollMode.SCROLL_INSENSITIVE);
while(sc.next()) {
String empName = (String)sc.get(0);
System.out.println(empName);
String empdept = (String)sc.get(1);
System.out.println(empdept);
}
The output of above programm will values of employeeName and employeeDept .
Now suppose you want to get the last record of the resultSet. With list() you would need to iterate the whole result. With ScrollableResults, you can use last() function.
Note that for ScrollableResults sc = session.createCriteria(Employee.class).scroll(); should be iterated as
while(sc.next()) {
Employee emp = (Employee)sc.get(0);
System.out.println(emp.getname);
}

Jpa named query: how to get a list of column

I have an entity orderdetails, where a user can have many ordernames I want to get all the ordername by userid using jpa named query. I tried this
SELECT o.orderName FROM OrderDetails o WHERE o.userId=:userId;
Since the return type will be List in the resultset, I executed the query like this
getEntityManager().createNamedQuery("getOrderNamesByUserId",
orderDetail.class).setParameter("userId", userId);
This obviously is not working. How can I get that query working? One way is to iterate the List but I wonder whether there is another way around?
Well this is non-compiled code snippet, you could try the following approach.
#Override
public List<OrderDetails> findOrders(Long userId) {
TypedQuery<OrderDetails> query = entityManager.createNamedQuery(
"OrderDetails.getOrderNamesByUserId", OrderDetails.class);
query.setParameter("userId", userId);
List<OrderDetails> list = query.getResultList();
return list;
}
If you just need to select one column(ordername), use getResultList() method.
Query query = getEntityManager().createNamedQuery("getOrderNamesByUserId", OrderDetail.class);
query.setParameter("userId", userId);
List<String> orderNameList = query.getResultList();

Hibernate criteria return page and rowcount

Using Hibernate Criteria i am trying to achieve pagination but the problem is that for every page fetch i have to make two db calls one for results and another for total records count.
Is there any efficient way so that in a single db call i can get both the data or i can reduce db calls.
Criteria criteria=session.createCriteria(Student.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.add(Restrictions.ne("enquiryStatus", ENQUIRY.JOINED));
criteria.setMaxResults(10);
criteria.setFirstResult((paginate.getStartIndex()-1)*10);
criteria.setProjection(Projections.rowCount());
//here i need to fetch total row count and records
Yes you need the separate query to get the total result count.
Query aCountQuery = session.createQuery("select count(s.id) from Student s
where s.enquiryStatus != :enquiryStatus");
aCountQuery.setParameter("enquiryStatus", ENQUIRY.JOINED);
Long resultCount = (Long)aCountQuery.uniqueResult();
or
Criteria criteria=session.createCriteria(Student.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.add(Restrictions.ne("enquiryStatus", ENQUIRY.JOINED));
criteria.setProjection(Projections.rowCount())
Long resultCount = (Long)criteria.uniqueResult();
Update
Now you can use same Criteria for results with pagination and result count
Criteria criteria=session.createCriteria(Student.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.add(Restrictions.ne("enquiryStatus", ENQUIRY.JOINED));
criteria.setMaxResults(10);
criteria.setFirstResult((paginate.getStartIndex()-1)*10);
List<Student> students = criteria.list();
criteria.setProjection(null);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
Long resultCount = (Long)criteria.uniqueResult();
As far As I know there is no direct method to do so.As simple as you can do is write a small hql query(my choice) ,Along with your main criteria.
Number count = (Number) session.createQuery(
"select count(s.id) from Student s").uniqueResult();

How to avoid hibernate default order by id?

I make this query:
String query = FROM Account acc WHERE acc.id = ? OR acc.id = ? or acc.id = ?...
I have array of ids:
long[] accountIds= {327913,327652,327910,330511,330643};
Then I make
getHibernateTemplate().find(query, accountIds);
I see that the list of accounts I get back from this query is:
327652,327910,327913,330511,330643, obviously , ordered by id.
Any chance I get it back in the order I wrote the ids?
Will appreciate all the help
You may want to use Criteria and its addOrder.
Something like this:
DetachedCriteria cr = DetachedCriteria.forClass(entityClass);
//Add expressions or restrictions to your citeria
//And add your ordering
cr.addOrder(Order.asc("yourID"));
List<T> ls = getHibernateTemplate().findByCriteria(cr);
return ls;
You can't do it on query level.
You can sort after loading from db, something like this
long[] accountIds= {327913,327652,327910,330511,330643};
List<Account> afterHql = getHibernateTemplate().find(query, accountIds);
List<Account> sortedList = new ArrayList<Acount>();
for (long id : accountIds)
{
for (Account account : afterHql)
{
if (account.getId() == id)
{
sortedList.add(account);
}
}
}
It is not possible to fetch results by providing any entity in OR Query or Restrictions.in(). As by deafult when you fire this kind of query it will search for the results id wise. So it will give you results id wise only. You can change the order by using Criteria either in asc or desc. And if you want to have results as per you enter id, then second answer is the only option.
You can only order by column values returned by the query, in a sequence defined by the data type . Wouldn't it be better to pre-order the IDs you supply, and order the query result by ID, so they come out in the same order?

Categories