I am trying to fetch value from database using HQL but am getting exceptions because value contains special characters. I am not able to figure out why.
Below is the code i am trying:
HotelMapping hotelMapping = null;
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.getTransaction();
tx.begin();
String hotelName = "A Fisher's Inn Motel";
Query query = session.createQuery("from HotelMapping hm where hm.hotelID.hotelName='"+hotelName+"'");
HotelMapping mapping = query.uniqueResult();
}
tx.rollback();
sessionFactory.close();
The pojos look like below:
Hotel.java
public class Hotel{
String hotelName;
double price;
//getters and setters
}
HotelMapping.java
public class HotelMapping{
#OneToOne(cascade = CascadeType.ALL)
Hotel hoteID
String location;
}
The query string
Query query = session.createQuery("from HotelMapping hm where hm.hotelID.hotelName='"+hotelName+"'"); gives me below exception :
Exception in thread "main" org.hibernate.QueryException: expecting ''', found '<EOF>' [from com.pb.model.HotelMapping hm where hm.hotelID.hotelName='A Fisher's Inn Motel']
I tried escaping the apostrophe but with no luck. I ven tried setting the query parameter but again i got exception
query.setParameter("hotelName", "A Fisher's Inn Motel");
It says Exception in thread "main" org.hibernate.QueryParameterException: could not locate named parameter [hotelName]
Please if someone could help me achieving a generalized solution for the special character handling?
You should never use concatenation to pass dynamic parameters like this. This is not only not efficient, but also not robust (since a single quote in the parameter value makes the query invalid) and insecure, since a malicious user could pass a value that changes the semantics of the query (google for "SQL injection attack").
Instead, use parameters:
Query query = session.createQuery(
"from HotelMapping hm where hm.hotelID.hotelName = :hotelName");
query.setString("hotelName", hotelName);
Related
I am getting an error with the following JPQL query:
#NamedQuery (name = "Customer.getById", query =
"SELECT o
FROM bub.Customer o
WHERE o.user_id = :myid")
[bub.Customer is the #Entity name]
This is an excerpt of the error message I'm receiving:
org.hibernate.HibernateException:
Errors in named queries:
Customer.getById\n
Caused by: org.hibernate.HibernateException:
Errors in named queries: Customer.getById
When I remove the WHERE clause Wildfly allows me to deploy my web app so I know there is something wrong wtih my WHERE clause. Specifically since the column name is user_id in my Customer table I believe there may be an issue with the underscore(_) in the JPQL. I've tried changing the WHERE clause to "WHERE o.userId = :myid" but that didn't work either.
How can I fix the WHERE clause so my website will deploy and still work the correct way?
EDIT:
The relevant method is this:
public static Customer getById (final EntityManager em, final long id)
{
return em.createNamedQuery ("Customer.getById", Customer.class).setParameter ("myid", id).getSingleResult ();
}
I don't think this is the issue though.
EDIT2:
It turns out this was the issue:
#ManyToOne (fetch = FetchType.LAZY)
#JoinColumn (name = "user_id")
private User user;
I ended up changing the JPQL query to this and now it's working:
#NamedQuery (name = "Customer.getById", query =
"SELECT o
FROM bub.Customer o
WHERE o.user = :myid")
In JPQL you don't use the column name, but the attribute name(unless you annotate something else)
I get this error
Exception in thread "main" java.lang.ClassCastException:
[Ljava.lang.Object; cannot be cast to xxx.xxx.xxx.Terminal
when i try this code; so what is wrong ??
for(int k=0;k<argTerminal.length;k++){
String hql = "select crimpkontakt from Terminal where id="+argTerminal[k];
Query query = session.createQuery(hql);
query.setMaxResults(1);
Terminal nameTerminal = (Terminal) query.uniqueResult();
If you want to select Terminal object your HQL should look like:
String hql = "from Terminal where id="+argTerminal[k]
Also in order to avoid SQL injection using parameters API is a preferred option:
Query query = session.createQuery("select from Terminal where id = :id");
query.setString("id", argTerminal[k]); // I assume that id is a String here
query.setMaxResults(1);
Even better if id is a primary key you can use session.get(Terminal.class, argTerminal[k])
I understand some might simply answer this question with "Why didn't you just Google it"... But I did, and the more I researched this the more confused I got. I'm trying to query my database with Hibernate, the query has a 'where' clause.
Now creating a database entry is easy enough, in the case where I have a 'User' class, I simply do this:
// Gets a new session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
// Creates a new User object
User user = new User("John", "p#55w0rd*", "john#doe.com");
// Save and commit
session.save(user);
session.getTransaction().commit();
But what do I do when I what to for instance
select * from Users where id = '3';
My Google searches pointed to something called HQL, which makes me wonder why I couldn't of just used straight JDBC then. Also it doesn't seem very object oriented. And then there's something like
session.createCriteria(.......
But I'm not sure how to use this.. Any help? Thanks guys.
When you use Native Query (non HQL ) you need to tell hibernate explicitely to handle it like below :
In below query createSQLQuery is special function to handle native sql's
String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(User.class);
query.setParameter("employee_id", 3);
List<User> results = query.list();
This can be done using criteria as well for that following is good starting point:
Criteria criteria = sess.createCriteria( User.class);
List<User> users= criteria.list();
http://www.developerhelpway.com/framework/hibernate/criteria/index.php
First of all, you need a hibernate.cfg.xml which contains properties for hibernate. This is e.g url, username and password, the driver and dialect. This file is placed in a package called resources.
You have to choose between using Hibernate Annotations example
or using hbm.xml files example
This is how you tell hibernate what your database is like. It wil automatically create queries for you based on how you annotates or defines in e.g user.hbm.xml.
Create a HibernateUtil.java class which holds the session factory.
You can fetch data from the database with
Criteria crit = getSessionFactory().getCurrentSession().createCriteria(User.class);
Example using queries:
List<?> hibTuppleResultList = currentSession.createQuery(
"from Person p, Employment e "
+ "where e.orgno like ? and p.ssn = e.ssn and p"
+ ".bankno = ?")
.setString(0, orgNo).setString(1, bankNo).list();
for (Object aHibTuppleResultList : hibTuppleResultList)
{
Object[] tuple = (Object[]) aHibTuppleResultList;
Person person = (Person) tuple[0];
hibList.add(person);
}
In the end all I really wanted was to know that if you don't want to use HQL you get something called 'Criteria Queries', and that in my case I'd do something like this:
Criteria cr = session.createCriteria(User);
cr.add(Restrictions.eq("id", 3));
List results = cr.list();
Me: "Thanks!"
Me: "No problem :)"
PS - we can really delete this question.
Query q = session.createQuery("from User as u where u.id = :u.id");
q.setString("id", "3");
List result = q.list();
Query with Criteria:
Criteria cr = session.createCriteria(User.class);
List results = cr.list();
Restrictions with Criteria:
Criteria cr = session.createCriteria(User.class);
cr.add(Restrictions.eq("id", 3));
// You can add as many as Restrictions as per your requirement
List results = cr.list();
You could also use it like this
List results = session.createCriteria(User.class).add(Restrictions.eq("id", 3)).list();
Some example for Crieteria Rsetriction query
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));
// To get records having fistName starting with zara cr.add(Restrictions.like("firstName", "zara%"));
// Case sensitive form of the above restriction.
cr.add(Restrictions.ilike("firstName", "zara%"));
// To get records having salary in between 1000 and 2000
cr.add(Restrictions.between("salary", 1000, 2000));
// To check if the given property is null
cr.add(Restrictions.isNull("salary"));
// To check if the given property is not null
cr.add(Restrictions.isNotNull("salary"));
// To check if the given property is empty
cr.add(Restrictions.isEmpty("salary"));
// To check if the given property is not empty
cr.add(Restrictions.isNotEmpty("salary"));
You can create AND or OR conditions using LogicalExpression restrictions as follows:
Criteria cr = session.createCriteria(Employee.class);
Criterion salary = Restrictions.gt("salary", 2000);
Criterion name = Restrictions.ilike("firstNname","zara%");
// To get records matching with OR condistions
LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );
// To get records matching with AND condistions
LogicalExpression andExp = Restrictions.and(salary, name);
cr.add( andExp );
List results = cr.list();
I think this will help you
I have a simple model which is just a chain of one-to-many relationships: Country -< City -< Street
The tables are mapped as entities and are returned as Map.
The following test method is producing odd results:
public static void main(String[] args) {
Session session = HibernateSessionFactory.getSession();
List<Map<String, Object>> results = null;
//Query using HQL and print results
System.out.println("FROM HQL =====================");
String hql = "from Street where City.Country.countryid = 1";
Query query = session.createQuery(hql);
results = query.list();
for(Map<String, Object> row : results) {
System.out.println(row);
}
//Query using Criteria and print results
System.out.println("FROM CRITERIA ================");
Criteria criteria = session.createCriteria("Street");
criteria.add(Restrictions.eq("City.Country.countryid", 1));
results = criteria.list();
for(Map<String, Object> row : results) {
System.out.println(row);
}
}
The top block which uses the HQL works as expected, but the bottom block falls over:
Output:
FROM HQL =====================
{streetname=Mayfair, City=org.hibernate.proxy.map.MapProxy#2b12e7f7, $type$=Street, streetid=1}
{streetname=Park Lane, City=org.hibernate.proxy.map.MapProxy#2b12e7f7, $type$=Street, streetid=2}
{streetname=Bond Street, City=org.hibernate.proxy.map.MapProxy#663b1f38, $type$=Street, streetid=3}
{streetname=Old Kent Road, City=org.hibernate.proxy.map.MapProxy#663b1f38, $type$=Street, streetid=4}
FROM CRITERIA ================
Exception in thread "main" org.hibernate.QueryException: could not resolve property: City.Country.countryid of: Street
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:67)
at org.hibernate.persister.entity.AbstractPropertyMapping.toColumns(AbstractPropertyMapping.java:82)
at org.hibernate.persister.entity.BasicEntityPropertyMapping.toColumns(BasicEntityPropertyMapping.java:54)
at org.hibernate.persister.entity.AbstractEntityPersister.toColumns(AbstractEntityPersister.java:1367)
at org.hibernate.loader.criteria.CriteriaQueryTranslator.getColumns(CriteriaQueryTranslator.java:457)
at org.hibernate.loader.criteria.CriteriaQueryTranslator.getColumnsUsingProjection(CriteriaQueryTranslator.java:417)
at org.hibernate.criterion.SimpleExpression.toSqlString(SimpleExpression.java:68)
at org.hibernate.loader.criteria.CriteriaQueryTranslator.getWhereCondition(CriteriaQueryTranslator.java:357)
at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:113)
at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:82)
at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:91)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1578)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:306)
at com.bar.foo(Main.java:33)
I can't see why the HQL can resolve City.Country.countryid but Criteria (Restrictions) can't.
Am I missing something obvious?
Because you used the wrong syntax for the hql query.
several faults:
Street.class instead of "Street"
Missing alias
use country directly instead of country.id
Try this:
Criteria criteria = session.createCriteria(Street.class)
.createAlias("city", "ci")
.add(Restrictions.eq("ci.country", country))
See the hibernate reference for more details.
I made a class called SpecializationBean which has two private fields:
private ArrayList<SelectItem> specializationItems= new ArrayList<SelectItem>();
private String specializationName;
I have ofcourse a getter and setter for those two.
and a buildSpecializationList method which builds the specializationItems list: (I call this method in the getter):
public void buildSpecializationList(){
List<Object[]> specializations = null;
try{
Session mySession = HibernateUtil.getAdmSessionFactory().getCurrentSession();
Transaction transaction = mySession.beginTransaction();
String sql = "SELECT J_Specialization_ID, Specialization_Name_Ar FROM J_Specialization WHERE J_Department_ID = '1000001'";
Query query = mySession.createSQLQuery(sql).addScalar("id", Hibernate.LONG).addScalar("name", Hibernate.STRING);
specializations = query.list();
}
catch(Exception e){
e.printStackTrace();
}
this.specializationItems = new ArrayList<SelectItem>(90);
for(Object[] sp: specializations ){
this.specializationItems.add(new SelectItem(sp[0],(String) sp[1]));
}
}
The problem is that I get a null pointer exception which shows that the list specializations (defined in the buildSpecializationList()) is null. I have tried the query myself on the table and it returns a result. I also tried HQL query (istead):
String sqlQuery = "Select JSpecializationId, specializationNameAr FROM JSpecializationWHERE JDepartmentId = '1000001'";
Query q = mySession.createQuery(sqlQuery);
But still, I get a null pointer exception which shows that the query returns me null result. Do you have any suggestions?
For anyone who encounters this problem using Hibernate ...... creating a new class and rewriting the whole thing may actually solve the problem!!!