Hibernate having difficulty with '#' character in HQL - java

Working with hibernate and spring social,
I am trying to query the database by email address.
when i do this query:
public Account findAccountByUsername(String username) {
Session session = sessionFactory.getCurrentSession();
String selectQuery = "FROM Account as account WHERE account.username = "+username;
Query query = session.createQuery(selectQuery);
#SuppressWarnings("unchecked")
List<Account> results = query.list();
if (!results.iterator().hasNext())
return null;
return results.iterator().next(); }
i get this exception
2013-01-22 14:37:13,090 [DEBUG] [HibernateTransactionManager,doBegin(),569] - Exposing Hibernate transaction as JDBC transaction [com.mchange.v2.c3p0.impl.NewProxyConnection#3b249bb2]
2013-01-22 14:37:13,352 [DEBUG] [QueryTranslatorImpl,parse(),272] - parse() - HQL: FROM masterPackage.model.orm.Account as account WHERE account.username = myEmail#gmail.com
2013-01-22 14:37:13,383 [DEBUG] [AbstractPlatformTransactionManager,processRollback(),843] - Initiating transaction rollback
2013-01-22 14:37:13,384 [DEBUG] [HibernateTransactionManager,doRollback(),672] - Rolling back Hibernate transaction on Session [org.hibernate.impl.SessionImpl#294a7134]
2013-01-22 14:37:13,385 [DEBUG] [JDBCTransaction,rollback(),186] - rollback
.......
2013-01-22 14:37:18,818 [WARN] [ProviderSignInController,oauth2Callback(),177] - Exception while handling OAuth2 callback (unexpected char: '#' [FROM masterpackage.model.orm.Account as account WHERE account.username = myEmail#gmail.com]). Redirecting to /signin
is there a way to work around this problem?
There is always a way to save the # character in the email address as some other character, but i am asking if there is something better then this solution.

Do not concatenate HQL query. Use named parameters instead. It is an implementation of Query Object Pattern in Hibernate.
For your case:
Session session = sessionFactory.getCurrentSession();
String selectQuery = "FROM Account as account WHERE account.username = :usernameParam";
Query query = session.createQuery(selectQuery);
query.setParameter("usernameParam", username);
#SuppressWarnings("unchecked")
List<Account> results = query.list();
if(results.isEmpty()){
return null;
} else {
return result;
}
Offtop: recommended never return null value for such method. Better is to return an empty collection. For example return new ArrayList<>(); Thus you able to use Null Object pattern implicitly.

Related

procedure call not working from java call

I have created a procedure which updates a table row in DB and returns a specific string(e.g 'done') after the update it returns a different response if the value is not updated(e.g 'fail').
When calling from MySQL tool it's updating the table and returning the value in response
call LoginCheck('9111111114','AGGR001002','11d3ad9315b7be5dd53b31a273b3b3aba5defe700808305aa16a3062b76658a791','DIST001007');
However when I am calling the same procedure from Java code it's returning the proper response i.e 'done', but when I am checking the table it seems that it has not updated the respective table row.
factory = DBUtil.getSessionFactory();
Session session = factory.openSession();
Transaction transaction = session.beginTransaction();
String status = "7000";
List objectList = null;
SQLQuery query = session.createSQLQuery("call LoginCheck(:userid,:AggId,:Password,:id)");
query.setString("userid", userid);
query.setString("AggId", AggId);
query.setString("Password", Password);
query.setString("id", id);
objectList = query.list();
I have already tried query.setParameter and query.ExecuteUpdate()
Please let me know if anything else is required from my side.
It seems that you have begin your transaction but not committed it . so try commit it .
Transaction transaction = session.beginTransaction();
transaction.commit()

Unexpected token error at table alias using hibernate

I am using Spring hibernate.
My code is as below:
String hql = "select a.candidate_id_fk, count(*) from Answers a , Question b where a.question_id_fk = b.id"+""
+"and a.answer=b.correct_answer group by a.candidate_id_fk";
Session session = sessionFactory.getCurrentSession();
List list = session.createQuery(hql).list();
Error:
org.hibernate.hql.internal.ast.ErrorCounter reportError
unexpected token: a

Trouble when using clase WHERE ... IN (list)

I'm having trouble when trying to retrieve from database using Hibernate. What I'm trying to do is to retrieve questions from the database (using Hibernate with HSQLDB) where the Tag tag is contained in the question list. Here is the error:
06-Jan-2017 19:43:26.021 WARN [http-apr-8080-exec-4] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions SQL Error: -5585, SQLState: 42585 06-Jan-2017 19:43:26.021 ERROR [http-apr-8080-exec-4] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions malformed numeric constant: .
Here the query:
Query query = session.createQuery("FROM Question q WHERE (:someTag) in (q.tagList) ORDER BY (q.creationDate) DESC").setParameter("someTag", tag).setMaxResults(amount);
And here the complete method:
public static List<Question> list(Tag tag, int amount){
Session session = HibernateUtil.getSession();
Query query = session.createQuery("FROM Question q WHERE (:someTag) in (q.tagList) ORDER BY (q.creationDate) DESC").setParameter("someTag", tag).setMaxResults(amount);
return query.list();
}
You need to use elements clause if you are trying to check whether a list contains an element, in this case, the query would look like this:
"FROM Question q WHERE :someTag in elements(q.tagList) ORDER BY (q.creationDate) DESC"

Is it safe enough?

Is insert statement like this is safe enough? Do I have to check if it's not SQL Injectionable?
#Autowired
private SessionFactory sessionFactory;
public void add(String title, String region, String def, String rangeStart,
String rangeEnd, Date extradition, Date expiration) {
Session session = null;
session = this.sessionFactory.getCurrentSession();
Query query = session
.createSQLQuery(
"INSERT INTO operators VALUES(NULL,:title,:region,:def,:rangeStart,:rangeEnd, :extradition, :expiration )")
.setString("title", title).setString("region", region)
.setString("def", def).setString("rangeStart", rangeStart)
.setString("rangeEnd", rangeEnd)
.setDate("extradition", extradition)
.setDate("expiration", expiration);
int updated = query.executeUpdate();
}
Yes, it is safe enough for SQL Injection attacks. Note that Query#executeUpdate will use a PreparedStatement behind the scenes for you to set the data for the parameters, which makes this statement safe enough.
PreparedStatement will write the Strings content directly in the specified fields, escaping any undesired value.
Still, note that if you have a bad design of your queries, you will be open to SQL Injection attacks. For example, if you create the query but append the String manually:
String sqlOpenToSqlInjection = "FROM operators WHERE stringField = " + stringVariable;
Query query = session.createSQLQuery(sqlOpenToSqlInjection);
//code to execute query...
More info:
Difference between Statement and PreparedStatement
Looks like you're using Hibernate as well, so it would be better if you save the entity. This would be similar but less code to handle/maintain.

JPA reuse some "previous" JDBC login credentials

I don't know if this is really a bug ... it seems that something remains "open".
I'm using EclipseLink 2.5 with com.microsoft.sqlserver.jdbc.SQLServerDriver.
In the second call at the createEntityManagerFactory method a wrong password is ignored and everything works as well ...
Do I have to reset or clean some kind of Connection or Session Object ?
String userId = "sa";
String psw = "rightPassword";
Map<String, Object> paramsConnect = new HashMap<String, Object>();
paramsConnect.put("javax.persistence.jdbc.user", userId);
paramsConnect.put("javax.persistence.jdbc.password", psw);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PU", paramsConnect);
EntityManager em = emf.createEntityManager();
Query q = em.createNativeQuery("SELECT * FROM Tab1");
List<Object[]> rows = q.getResultList();
System.err.println(rows.get(0));
em.clear();
em.close();
emf.close();
psw = "wrongPassword";
EntityManagerFactory emf1 = Persistence.createEntityManagerFactory("PU", paramsConnect);
EntityManager em1 = emf1.createEntityManager();
Query q1 = em1.createNativeQuery("SELECT * FROM Tab2");
List<Object[]> rows1 = q1.getResultList();
System.err.println(rows1.get(0));
If you want to change the value with key 'javax.persistence.jdbc.password' in your HashMap you need to change the line:
psw = "wrongPassword";
with the line:
paramsConnect.put("javax.persistence.jdbc.password", "wrongPassword");
The method put will replace the value of an existing key and will create it if doesn't exist.

Categories