Eclipselink cache is not used for Criteria API queries - caching

I am using Criteria API for creation of queries which are usually not using PK as identifier. I am not able to force eclipselink store result to cache.
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Book> criteriaQuery = builder.createQuery(MetadataTextValue.class);
Root<Book> root = criteriaQuery.from(MetadataTextValue.class);
criteriaQuery = criteriaQuery.where(builder.equal(root.get("value"),value.getValue()));
TypedQuery<Book> typedQuery = em.createQuery(criteriaQuery);
MetadataTextValue metadataTextValue = typedQuery.getSingleResult();
But it works for:
Query query = entityManager.createQuery("select m from MetadataTextValue m where m.value = :value");
query.setParameter("value",value.getValue());
return (MetadataTextValue)query.getSingleResult();
So there should not be problem with the entity and value itself. I tried to debug Eclipselink search and when using criteria API, after first cache miss result is added to cache, but next search for same value is again cache miss, but is not added.

Related

Criteria Query to retrieve data from DB using specification and predicate

I have two tables (user, vehicles) and i want to write criteria query to retrieve data from db using criteria query specification and predicate to both Join Tables.
select ur.id, count (ur.vehicle_FK) from user so
inner join VEHICLE vhe on vhe.user_id_FK = ur."ID"
group by ur.id, vhe.user_id_FK;
How to implement it using criteria query ??
Try something like this :
Criteria criteria = session.createCriteria(User.class, "user");
criteria.createAlias("user.vehicle_FK", "vehicle", Criteria.INNER_JOIN);
criteria.setProjection(
Projections.projectionList().add(Projections.groupProperty("user.id"))
.add(Projections.countDistinct("user.id")));
Parameters in Criteria Queries
The following query string represents a JPQL query with a parameter:
SELECT c FROM Country c WHERE c.population > :p
An equivalent query can be built using the JPA criteria API as follows:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Country> q = cb.createQuery(Country.class);
Root<Country> c = q.from(Country.class);
ParameterExpression<Integer> p = cb.parameter(Integer.class);
q.select(c).where(cb.gt(c.get("population"), p));
The ParameterExpression instance, p, is created to represent the query parameter. The where method sets the WHERE clause. As shown above, The CriteriaQuery interface supports method chaining. See the links in the next sections of this page for detailed explanations on how to set criteria query clauses and build criteria expressions.
You can find more examples here
https://www.objectdb.com/java/jpa/query/criteria
Remember to post an answer when you find one! :)

Spring JPA #Query Annatotion disadvantages

Hi I use spring jpa to access my data in my spring boot project.I am wondering that is there any difference between #Query annatotation and critearia api in jpa.Are they totaly same or is there any difference(Their writing styles are different ,and I mean any performance or other issue between them)
Mostly I prefer #Query annotation it looks simple.Or any other option some one can advice like #Query or criteria api in spring jpa.And is there any disadvantages of #Query style?
#Query("SELECT u FROM User u WHERE u.status = 1")
Collection<User> findAllActiveUsers();
List<Book> findBooksByAuthorNameAndTitle(String authorName, String title) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Book> cq = cb.createQuery(Book.class);
Using #Query we can pass static query or pre compiled query so we can perform both select and non-select operations on the data
where as Criteria is suitable for executing Dynamic Queries such requirements occurs when data are know at run time
but using criteria api we can only perform select operations on the data.
For example
#Query(value = "SELECT u FROM User u")
List<User> findAllUsers(Sort sort);
We can also work with pre compiled query using #Query
For Example
#Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")
User findUserByStatusAndNameNamedParams(
  #Param("status") Integer status,
  #Param("name") String name);)
Dynamic queries like
Criteria cr = session.createCriteria(Employee.class);
// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));
// To get records having salary less than 2000
cr.add(Restrictions.lt("salary", 2000));
Actual use of Dynamic queries comes when we'll encounter the need for building SQL statements based on conditions or data sets whose values are only known at runtime. And, in those cases, we can't just use a static query So we can't just use the #Query annotation since we can't provide a static SQL statement.In such case we use Criteria API
For more info follow the link provided
#Query and Criteria

Spring JPA - How to create a Pageable with a NativeQuery?

I try to do the following inside a Spring Boot application : create a native query and page it so it can returns a page of a given number of elements from a #RestController.
Here's the snippet of my code, where em is the #PersistanceContext EntityManager, and the repository method is the following, knowing that queryString is the native query :
Query searchQuery = em.createNativeQuery(this.queryString, MyEntity.class);
List<MyEntity> resultsList = searchQuery.getResultList();
return new PageImpl<>(resultsList, PageRequest.of(index,size), resultsList.size());
My problem is that the Page returned has a content of the complete query result, not a content of the size of size parameter inside the PageRequest.of.
Has anybody faced the same issue and could give a working example on how to paginate a nativeQuery please ?
Thanks for your help
You are mixing Spring Data JPA (Pageable) with JPA EntityManager. You can't do that. If you are already using a native query then simply put the pagination in the query. You can use what your database supports, for example the standard:
SELECT [a_bunch_of_columns]
FROM dbo.[some_table]
ORDER BY [some_column_or_columns]
OFFSET #PageSize * (#PageNumber - 1) ROWS
FETCH NEXT #PageSize ROWS ONLY;
this is example of using native query with pagination:
#Query("SELECT c FROM Customer As c INNER JOIN Offer as f on f.id=c.specialOffer.id inner join User As u on u.id=f.user.id where u.id=?1 And c.status=?2")
Page<Customer> getAllCustomerToShop(Integer shopId,String status,Pageable pageable)
and then you can call it as:
getAllCustomerToShop(shopId,"status",PageRequest.of(index, PAGE_SIZE));
Modify your code as follows
Query searchQuery = em.createNativeQuery(this.queryString, MyEntity.class)
.setFirstResult(pageable.getPageNumber() * pageable.getPageSize())
.setMaxResults(pageable.getPageSize());

HQL like operator for case insensitive search

I am implementing an autocomplete functionality using Jquery, when I type the name, it fetches the record from the db, The records stored in db are mixture of capital & small letters. I have written a HQL Query which fetches me the records with case-sensitive, but I need to records irrespective of case. Here is the query,
List<OrganizationTB> resultList = null;
Query query = session.createQuery("from DataOrganization dataOrg where dataOrg.poolName
like '%"+ poolName +"%'");
resultList = query.list();
Ex : If I have pool names, HRMS Data set, Hrms Data, Hr data etc... if I type HR or hr I need to get all the 3 records, which I'm not able to.
Please help...
change your query to
"from DataOrganization dataOrg where lower(dataOrg.poolName)
like lower('%"+ poolName +"%')"
for more information have a look 14.3 doc
A good solution is:
List<OrganizationTB> resultList = null;
Query query = session.createQuery("from DataOrganization dataOrg where lower(dataOrg.poolName) like lower(:poolName)");
query.setParameter("poolName", '%'+poolName+'%', StringType.INSTANCE);
resultList = query.list();
So you protect your code from SQL injection

How to get total count in hibernate full text search?

I am trying using hibernate full text by following this link:
hibernate/search/4.1/reference/en-US/html/getting-started
Basically, it works, but I want to know how to get total count while I execute a full text query,then I can tell user how many results and how many pages would be in such a query.
Here is the code(Using JPA to create and execute a search):
EntityManager em = entityManagerFactory.createEntityManager();
FullTextEntityManager fullTextEntityManager =
org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
em.getTransaction().begin();
// create native Lucene query unsing the query DSL
// alternatively you can write the Lucene query using the Lucene query parser
// or the Lucene programmatic API. The Hibernate Search DSL is recommended though
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity( Book.class ).get();
org.apache.lucene.search.Query query = qb
.keyword()
.onFields("title", "subtitle", "authors.name", "publicationDate")
.matching("Java rocks!")
.createQuery();
// wrap Lucene query in a javax.persistence.Query
javax.persistence.Query persistenceQuery =
fullTextEntityManager.createFullTextQuery(query, Book.class);
persistenceQuery.setFirstResult((page - 1) * PAGECOUNT);
persistenceQuery.setMaxResults(PAGECOUNT);
// execute search
List result = persistenceQuery.getResultList();
em.getTransaction().commit();
em.close();
In SQL, I can use select count(*) from something, but here I don't know how to do that. I want to just fetch one page of data every time and use another API to get total count.
query.getResultSize(); //return the total number of matching ... regardless of pagination
I'm not sure if there is such a way when using the Hibernate full text search.
If you want to know the total number of results then you have to perform the full query. After you have the full count you can set your page limiter and perform it again.
javax.persistence.Query persistenceQuery =
fullTextEntityManager.createFullTextQuery(query, Book.class);
int count = persistenceQuery.getResultList().size();
persistenceQuery =
fullTextEntityManager.createFullTextQuery(query, Book.class);
persistenceQuery.setFirstResult((page - 1) * PAGECOUNT);
persistenceQuery.setMaxResults(PAGECOUNT);
List result = persistenceQuery.getResultList();
For Hibernate(maybe for JPA)
public interface FullTextQuery extends Query
in other words, you need use
org.hibernate.search.FullTextQuery query = fullTextEntityManager.createFullTextQuery(query, Book.class);
instead of
org.hibernate.Query query = fullTextEntityManager.createFullTextQuery(query, Book.class);
and method getResultSize() will be available
When using directly Lucene/Solr, I usually use a hack* by searching for *:*, setting it to return the least possible results BUT that does return the total result count for "everything", and I proceed to extract it. Basically it's the same as the SELECT count(*) FROM whatever :P
*I say hack because I'm not sure if it's supposed to be that way or not, but it works for me...

Resources