I'm trying to write a hibernate query to search if table Room contains roomname which contains part of string.The string value is in a variable. I wrote a query to get exact room name from the table.
findRoom(String name) {
Query query = em.createQuery("SELECT a FROM Room a WHERE a.roomname=?1");
query.setParameter(1, name);
List rooms = query.getResultList();
return rooms;
}
In sql the query is something like this:
mysql_query("
SELECT *
FROM `table`
WHERE `column` LIKE '%"name"%' or '%"name"' or '"name"%'
");
I want to know the hql query for searching the table that matches my query. I can not use string directly, so the search query has to be veriable based and I need all three types in a query, if it's begin with name, or contains name or ends name.
I would do something like that:
findRoom(String name) {
Query query = em.createQuery("SELECT a FROM Room a"
+ "WHERE a.roomname LIKE CONCAT('%',?1,'%')");
query.setParameter(1, name);
List rooms = query.getResultList();
return rooms;
}
Use like instead of =:
Query query = em.createQuery("SELECT a FROM Room a WHERE a.roomname like ?1");
query.setParameter(1, "%"+name+"%");
Related
Hi guys I am new to jpa, named queries, etc.. and I need something like this:
select t from :tableName t
Later in code I want something like this:
em.createQuery(...);
setParameter("tableName", "Person")
Result would be:
select * from person
How to write such a generic jpa query statement allowing to select all rows from :tableName which may be defined at runtime? thanks in advance
Try this I think this works well
EntityManagerFactory emfactory=Persistence.createEntityManagerFactory("Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
Query query = entitymanager.
createQuery("Select p from Person p");
List<String> list = query.getResultList();
setParameter("foo", foo) is used to set the value for column of the table not to set the table name. I do not think it will work, as you want to set the table name dynamically.
You can try this:
public returnType foo(String tableName){
String jpql = "SELECT t FROM " + tableName+ " t";
Query query = em.createQuery(jpql);
//rest of the code
}
I'm triggering a query using HQL, normally it should return empty resultset as it doesn't have any records w.r.t it. But, it throws
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
My code is
String hql = "FROM com.pck.Person where userId = " + userId;
Query query = session.createQuery(hql);
#SuppressWarnings("unchecked")
List<Dashboard> listUserDetails = query.list(); <-- Problem here.
I'm expecting list size is 0 because there are no records w.r.t userId passed.
What changes do I need to do?
Lets say the value of userId was "abc12"
Given your code, the value of the string called hql would become:
"FROM com.pck.Person where userId = abc12"
If you took the value of that string and tried to run it as a query on any database, most of them would fail to understand that abc12 is a string. Normally it would be interpreted as a variable.
As other users mentioned including the single quotes would produce the desired query, but the recommended way to assign parameter values is this:
String hql = "FROM com.pck.Person where userId = :id"
query.setParameter("id", userId);
Looks like you are missing single quotes around userid.
Try with "FROM com.pck.Person where userId = '" + userId + "'";
or
Use named parameters with query.setParameter("userid", userId);
Posting the full stacktrace would help if this doesn't solve.
Query :
#Query("Select p.name,t.points from Player p,Tournament t where t.id=?1 And p.id=t.player_id")
I have my player and tournament entity and their corresponding JPA repositories. But the problem is we can get only entities from our query, but i want to do above query, please help me with this i am new to it.
this is my sql query i want to add but where to add i am not getting:
Select p.name, t.points_rewarded from player p, participant t where t.tournament_id="1" and t.player_id=p.id;
This is how you can do it with JPQL for JPA:
String queryString = "select p.name, t.points from Tournament t," +
" Player p where t.player_id=p.id " +
"and t.id= :id_tournament";
Query query = this.entityManager.createQuery(queryString);
query.setParameter("id_tournament", 1);
List results = query.getResultList();
You can take a look at this JPA Query Structure (JPQL / Criteria) for further information about JPQL queries.
And this is ho you can do it using HQL for Hibernate, these are two ways of doing it:
String hql = "SELECT p.name, t.points from Player p,Tournament t WHERE t.id= '1' And p.id=t.player_id";
Query query = session.createQuery(hql);
List results = query.list();
Or using query.setParameter() method like this:
String hql = "SELECT p.name, t.points from Player p,Tournament t WHERE t.id= :tournament_id And p.id=t.player_id";
Query query = session.createQuery(hql);
query.setParameter("tournament_id",1);
List results = query.list();
You can take a look at this HQL Tutorial for further information about HQL queries.
Note:
In both cases you will get a list of Object's array List<Object[]> where element one array[0] is the p.name and the second one is t.points.
TypedQuery instead of normal Query in JPA
this is what i was looking for, thanks chsdk for help, i have to create pojos class, and in above link answer is working fine foe me,
Here is my code sample
String querystring = "SELECT new example.restDTO.ResultDTO(p.name,t.pointsRewarded) FROM Player p, Participant t where t.tournamentId=?1 AND t.playerId = p.id ORDER by t.pointsRewarded DESC";
EntityManager em = this.emf.createEntityManager();
try {
Query queryresults = em.createQuery(querystring).setParameter(1, tournamentId);
List<ResultDTO> result =queryresults.getResultList();
return new ResponseEntity<>(result, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
} finally {
if (em != null) {
em.close();
}}
I am developing an application using hibernate. When I try to create a Login page, The problem of Sql Injection arises.
I have the following code:
#Component
#Transactional(propagation = Propagation.SUPPORTS)
public class LoginInfoDAOImpl implements LoginInfoDAO{
#Autowired
private SessionFactory sessionFactory;
#Override
public LoginInfo getLoginInfo(String userName,String password){
List<LoginInfo> loginList = sessionFactory.getCurrentSession().createQuery("from LoginInfo where userName='"+userName+"' and password='"+password+"'").list();
if(loginList!=null )
return loginList.get(0);
else return null;
}
}
How will i prevent Sql Injection in this scenario ?The create table syntax of loginInfo table is as follows:
create table login_info
(user_name varchar(16) not null primary key,
pass_word varchar(16) not null);
Query q = sessionFactory.getCurrentSession().createQuery("from LoginInfo where userName = :name");
q.setParameter("name", userName);
List<LoginInfo> loginList = q.list();
You have other options too, see this nice article from mkyong.
You need to use named parameters to avoid sql injection. Also (nothing to do with sql injection but with security in general) do not return the first result but use getSingleResult so if there are more than one results for some reason, the query will fail with NonUniqueResultException and login will not be succesful
Query query= sessionFactory.getCurrentSession().createQuery("from LoginInfo where userName=:userName and password= :password");
query.setParameter("username", userName);
query.setParameter("password", password);
LoginInfo loginList = (LoginInfo)query.getSingleResult();
What is SQL Injection?
SQL Injection happens when a rogue attacker can manipulate the query
building process so that he can execute a different SQL statement than
what the application developer has originally intended
How to prevent the SQL injection attack
The solution is very simple and straight-forward. You just have to make sure that you always use bind parameters:
public PostComment getPostCommentByReview(String review) {
return doInJPA(entityManager -> {
return entityManager.createQuery("""
select p
from PostComment p
where p.review = :review
""", PostComment.class)
.setParameter("review", review)
.getSingleResult();
});
}
Now, if some is trying to hack this query:
getPostCommentByReview("1 AND 1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) )");
the SQL Injection attack will be prevented:
Time:1, Query:["select postcommen0_.id as id1_1_, postcommen0_.post_id as post_id3_1_, postcommen0_.review as review2_1_ from post_comment postcommen0_ where postcommen0_.review=?"], Params:[(1 AND 1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) ))]
JPQL Injection
SQL Injection can also happen when using JPQL or HQL queries, as demonstrated by the following example:
public List<Post> getPostsByTitle(String title) {
return doInJPA(entityManager -> {
return entityManager.createQuery(
"select p " +
"from Post p " +
"where" +
" p.title = '" + title + "'", Post.class)
.getResultList();
});
}
The JPQL query above does not use bind parameters, so it’s vulnerable to SQL injection.
Check out what happens when I execute this JPQL query like this:
List<Post> posts = getPostsByTitle(
"High-Performance Java Persistence' and " +
"FUNCTION('1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) ) --',) is '"
);
Hibernate executes the following SQL query:
Time:10003, QuerySize:1, BatchSize:0, Query:["select p.id as id1_0_, p.title as title2_0_ from post p where p.title='High-Performance Java Persistence' and 1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) ) --()=''"], Params:[()]
Dynamic queries
You should avoid queries that use String concatenation to build the query dynamically:
String hql = " select e.id as id,function('getActiveUser') as name from " + domainClass.getName() + " e ";
Query query=session.createQuery(hql);
return query.list();
If you want to use dynamic queries, you need to use Criteria API instead:
Class<Post> entityClass = Post.class;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> query = cb.createTupleQuery();
Root<?> root = query.from(entityClass);
query.select(
cb.tuple(
root.get("id"),
cb.function("now", Date.class)
)
);
return entityManager.createQuery(query).getResultList();
I would like to add here that is a peculiar SQL Injection that is possible with the use of Like queries in searches.
Let us say we have a query string as follows:
queryString = queryString + " and c.name like :name";
While setting the name parameter, most would generally use this.
query.setParameter("name", "%" + name + "%");
Now, as mentioned above traditional parameter like "1=1" cannot be injected because of the TypedQuery and Hibernate will handle it by default.
But there is peculiar SQL Injection possible here which is because of the LIKE Query Structure which is the use of underscores
The underscore wildcard is used to match exactly one character in
MySQL meaning, for example, select * from users where user like
'abc_de'; This will produce outputs as users that start with abc, end
with de and have exactly 1 character in between.
Now, if in our scenario, if we set
name="_" produces customers whose name is at least 1 letter
name="__" produces customers whose name is at least 2 letters
name="___" produces customers whose name is at least 3 letters
and so on.
Ideal fix:
To mitigate this, we need to escape all underscores with a prefix .
___ will become \_\_\_ (equivalent to 3 raw underscores)
Likewise, the vice-versa query will also result in an injection in which %'s need to be escaped.
We should always try to use stored Procedures in general to prevent SQLInjection.. If stored procedures are not possible; we should try for Prepared Statements.
I am a bit lost when it comes to retrieving results from the database.
My MemberModel consists of 4 fields: id, username, password and email. I have been able to successfully save it to database.
Now I need to retrieve an id of a member who's username equals "Test".
I tried something along the lines:
SQLQuery query = session.createSQLQuery("SELECT id FROM members WHERE username = :username");
query.setString("username", username);
List<MemberModel> returnedMembers = query.list();
MemberModel member = returnedMembers.get(0);
int id = member.getId();
However I get an error that member.getId() cannot be converted to int, since it is MemberModel... But the getter getId() returns int.
I am quite confused. The question is: what would be the easiest and fastes way to retrieve member id based on condition (value of username)?
You are using a native SQL query, but should use HQL query. That means you have to change the query to:
session.createQuery("SELECT m FROM MemberModel m WHERE m.username = :username")
I would change your code into something like this:
public MemberModel getMember(String username) {
Query query = sessionFactory.getCurrentSession().createQuery("from " + MemberModel.class.getName() + " where username = :username ");
query.setParameter("username", username);
return (MemberModel) query.uniqueResult();
}
Then you should be able to do:
MemberModel model = someInstance.getMember("someUsername");
int id = model.getId();
You can also use criteria and restrictions api.
Criteria criteria = session.createCriteria(MemberModel.class);
criteria.add(Restrictions.eq("username", username));
MemberModel member=(MemberModel)criteria.uniqueResult();