How query cache works for scalar results? - java

I am new to Hibernate and I have the following piece of code in my DAO implementation class:
public Integer getEmployeeCode(String userName) {
Session session = sessionfactory.getCurrentSession();
Query q = session.createQuery("select emp.employeeCode from Employee emp where emp.userName = :username");
q.setString("username",userName);
Integer p = (Integer) q.setCacheRegion("UserNameToCode").setCacheable(true).uniqueResult();
I am using Hibernate with EhCache. I am wondering if I am using query cache correctly here? I understand that for domain objects, the query caches stores the mapping from query string and binding parameters to primary keys. However, how is the scalar values being cached in memory?

You might want to take a look at this excellent article about the 2nd level cache.
I am not quite sure, but I think you should not query for the scalar value but query the Employee by userName and return emp.getEmployeeCode() in your DAO method to take advantage of the 2nd level and query cache:
#Entity
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
class Employee {
#Column
Integer employeeCode;
}
public Integer getEmployeeCode(String userName) {
Session session = sessionfactory.getCurrentSession();
Query q = session.createQuery("from Employee emp where emp.userName = :username");
q.setString("username", userName);
Employee emp = q.setCacheRegion("Employee").setCacheable(true).uniqueResult();
return emp.getEmployeeCode();
}

Related

Hibernate Criteria searching request with One to Many relationship

I've tried to do it like:
session = HibernateUtil.getSessionFactory().openSession();
Criteria cr = session.createCriteria(Car.class);
cr.createAlias("vendor", "vendor");
cr.add( Restrictions.eq("vendor.name", input));
results = (List<Car>) cr.list();
And also like:
session = HibernateUtil.getSessionFactory().openSession();
Criteria cr = session.createCriteria(Car.class);
cr.createCriteria("vendor").add(Restrictions.eq("name", input));
results = (List<Car>) cr.list();
Both realizations just return all data, not specified with search query.
In the Car Class I've got relationship:
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="id_vendor", nullable=false)
public Vendor getVendor() {
return this.vendor;
}
And also I've got thename column at the Vendor class at which I'm trying to search.
So how possibly I could do such search request?
Thanks.
You need to assign your criteria back to the original object.
The reason you get all the cars back is because the line of code adding your vendor into the query creates you a new criteria object which you are then not using.
Change:
session = HibernateUtil.getSessionFactory().openSession();
Criteria cr = session.createCriteria(Car.class);
cr.createCriteria("vendor").add(Restrictions.eq("name", input)); //Does nothing
results = (List<Car>) cr.list();
into this:
session = HibernateUtil.getSessionFactory().openSession();
Criteria cr = session.createCriteria(Car.class);
cr = cr.createCriteria("vendor").add(Restrictions.eq("name", input));
results = (List<Car>) cr.list();
And it should work.
if you wont get unique result of Car.class you nedd set ResultTransformer
Criteria cr = session.createCriteria(Car.class);
cr.createAlias("vendor", "vendor");
cr.add( Restrictions.eq("vendor.name", input));
crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
results = (List<Car>) cr.list();

Returnings two results sets using JPA

I am using a JPA query to get a result set, then within the same class, I would like to conditionally get more data. Here's what it looks like:
public SchoolUser getCandidatesAsJson(#PathParam("applicationId") String applicationId, #PathParam("userPassword") String userPassword ) {
EntityManager em = createEM();
Query query = em.createQuery("SELECT su FROM SchoolUser su WHERE su.applicationId LIKE :applicationId and su.userPassword LIKE :userPassword", SchoolUser.class);
query.setParameter("applicationId", applicationId);
query.setParameter("userPassword", userPassword);
List <SchoolUser> schoolUser = query.getResultList();
if(!schoolUser.isEmpty()) {
SchoolUser loginRecord = schoolUser.get(0);
int teacherId = loginRecord.getTeacherId();
int studentId = loginRecord.getStundentId();
if(teacherId!=0){
TypedQuery<Classroom> query2 = em.createQuery("SELECT c FROM Classroom c where c.teacherId = :teacherId ORDER BY c.period", Classroom.class);
query2.setParameter("teacherId", teacherId);
List <Classroom> teacherClassList = query2.getResultList();
if(!teacherClassList.isEmpty()){
//put 2nd results set in SchoolUser object - line is commented because it causes an erro
//loginRecord.setClassRooms(teacherClassList);
}
} else if(studentId!=0){
TypedQuery<ClassroomStudent> query3 = em.createQuery("SELECT cs FROM ClassroomStudent cs where cs.statusId = 1 AND cs.studentId = :studentId", ClassroomStudent.class);
query3.setParameter("studentId", studentId);
//put results in SchoolUser object
}
return loginRecord;
} else {
SchoolUser emptyRecord = new SchoolUser();
return emptyRecord;
}
}
The error comes from putting the Classroom JPA object into the SchoolUser object - since these two objects don't have a direct relationship.
Any way that I can accomplish this with JPA?
If you do not want to persist the classroom (or any other attribute for that matter) then the #Transient annotation allows you to ignore a particular field so that JPA won't try to map it.
This annotation specifies that the property or field is not
persistent. It is used to annotate a property or field of an entity
class, mapped superclass, or embeddable class.
Example:
#Entity
public class Employee {
#Id int id;
#Transient User currentUser;
...
}

Cannot Cast HibernateQuery resuly list to Object class

I am using the following query to fetch data from db in hibernate
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Query q = session.createSQLQuery("select name,addr1,addr2,postal_code,country,email," +
"tel1,tel2,HeadOffice_id,Subscription_id from Restaurant " +
"where id=" +id);
session.getTransaction().commit();
Restaurant rest = (Restaurant)result.get(0);
But this is returning exception
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.hibernate.model.Restaurant
I also tried this way as well not sure whats doing
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass(Restaurant.class);
SessionFactory factory= config.configure().buildSessionFactory();
Session session =factory.getCurrentSession();
session.beginTransaction();
Query q = session.createSQLQuery("select name,addr1,addr2,postal_code,country,email," +
"tel1,tel2,HeadOffice_id,Subscription_id from Restaurant " +
"where id=" +id);
java.util.List<Restaurant> result = (List<Restaurant>)q.list();
session.getTransaction().commit();
Restaurant rest = (Restaurant)result.get(0);
Again I am getting the same exception. How can i do this with hibernate?
Thanks
Your query doesn't return instances of the Restaurant entity. It returns individual fields from this entity. The result of such a query is a List<Object[]>, each Object[] containing all the selected fields.
See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#queryhql-select:
Queries can return multiple objects and/or properties as an array of type Object[]:
If you want your query to returninstances of Restaurant, it should be
select r from Restaurant r where id = :id
And please, don't use concatenation to pass your parameter. Use named parameters as the above query.
as simple as:
Restaurant rest = (Restaurant)session.get(Restaurant.class, id);

Select all items from a list in hibernate

I have a list of product ids and I want to get all the products from my db with a hibernate query. How can I do this?
List<Integer> list = custumor.getCart();
Query query = query("select product from Product product where product.id =: list");
I know this isn't the best way to solve this, but I just want to know how I can test for all the values in a list.
There are two things you'll need to do... The first is to change your HQL to the following (making use of IN), and the second is to bind your parameter list:
Query query = query("select product from Product product where product.id IN :list")
.setParameterList("list", list);
Not sure I get you but check out this link: http://www.coderanch.com/t/217864/ORM/java/Hibernate-retrieve-data-database
Specifically this snippet:
public static void retrieve() {
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass(User.class);
SessionFactory factory= config.configure().buildSessionFactory();
Session session = factory.getCurrentSession();
session.beginTransaction();
Query queryResult = session.createQuery("from User");
java.util.List allUsers;
allUsers = queryResult.list();
for (int i = 0; i < allUsers.size(); i++) {
User user = (User) allUsers.get(i);
}
System.out.println("Database contents delivered...");
}
Actually I just re-read your question and I see you want a sub select. You should consider using a query like:
List<Integer> list = custumor.getCart();
Query query = query("select product from Product product where product.id IN (: list)");

IN-clause in HQL or Java Persistence Query Language

I have the following parametrised JPA, or Hibernate, query:
SELECT entity FROM Entity entity WHERE name IN (?)
I want to pass the parameter as an ArrayList<String>, is this possible? Hibernate current tells me, that
java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String
Is this possible at all?
ANSWER: Collections as parameters only work with named parameters like ":name", not with JDBC style parameters like "?".
Are you using Hibernate's Query object, or JPA? For JPA, it should work fine:
String jpql = "from A where name in (:names)";
Query q = em.createQuery(jpql);
q.setParameter("names", l);
For Hibernate's, you'll need to use the setParameterList:
String hql = "from A where name in (:names)";
Query q = s.createQuery(hql);
q.setParameterList("names", l);
in HQL you can use query parameter and set Collection with setParameterList method.
Query q = session.createQuery("SELECT entity FROM Entity entity WHERE name IN (:names)");
q.setParameterList("names", names);
Leaving out the parenthesis and simply calling 'setParameter' now works with at least Hibernate.
String jpql = "from A where name in :names";
Query q = em.createQuery(jpql);
q.setParameter("names", l);
Using pure JPA with Hibernate 5.0.2.Final as the actual provider the following seems to work with positional parameters as well:
Entity.java:
#Entity
#NamedQueries({
#NamedQuery(name = "byAttributes", query = "select e from Entity e where e.attribute in (?1)") })
public class Entity {
#Column(name = "attribute")
private String attribute;
}
Dao.java:
public class Dao {
public List<Entity> findByAttributes(Set<String> attributes) {
Query query = em.createNamedQuery("byAttributes");
query.setParameter(1, attributes);
List<Entity> entities = query.getResultList();
return entities;
}
}
query.setParameterList("name", new String[] { "Ron", "Som", "Roxi"}); fixed my issue

Categories

Resources