MYSQL+Hibernate, Query cannot be created - java

Can someone help me to have a look at what is wrong with my query?
Java code :
public boolean fValidLogin(String fUsername, String fPassword) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
String query = "SELECT fusername,fpassword FROM flogin WHERE fusername=" + fUsername + " AND fpassword=" + fPassword + "";
Query DBquery = session.createQuery(query);
for (Iterator it = DBquery.iterate(); it.hasNext();) {
it.next();
count++;
}
System.out.println("Total rows: " + count);
if (count == 1) {
return true;
} else {
return false;
}
}
MYSQL Code:
SELECT fusername,fpassword FROM flogin WHERE fusername="SAS" AND fpassword="Sas123"

Try this first:
"SELECT fusername,fpassword FROM flogin WHERE fusername=\"" + fUsername + "\" AND fpassword=\"" +fPassword +"\""
By the way you are tring to use a native query. Maybe you should consider to use "createNativeQuery" instead of "createQuery"

Your query is a victim of an SQL Injection, it can also cause syntax error, instead you have to use setParameter with a JPQL query :
String query = "SELECT f FROM flogin f WHERE f.fusername = ? AND f.fpassword = ?";
Query dBquery = session.createQuery(query);
dBquery.setParameter(0, fUsername);//set username variable
dBquery.setParameter(1, fPassword);//set password variable
To get the nbr of result you can just call Query::list()
int count = dBquery.list().size();
Or just :
return dBquery.list().size() == 1;
The real problem in your query is that the String should be between two quotes (but i don't advice with solution)
fusername='" + fUsername + "'
//--------^_________________^
Note: Your query is not a JPQL Query, it seems a native query, if that you have to use session.createNativeQuery(query);.

Related

How to execute Pre-build Query in Java Spring

I need to execute pre-build SQL query in java spring, I created query as follows,
String query = "select * from device where";
if (status != null) {
query += " status = "+status;
}
if (cinema != "") {
query += " and cinema_code = \'"+cinema+"\'";
}
if (content_profile != "") {
query += " and content_profile = \'"+content_profile+"\'";
}
if (mac != "") {
query += " and mac = \'"+mac+"\'";
}
Build query:
select *
from device
where status = 2
and cinema_code = 'AL10'
and content_profile = 'signage'
You can use Spring Data JPA Specifications for dynamic queries.
Give a look here:
https://www.baeldung.com/rest-api-search-language-spring-data-specifications
If you don't want JPA you can use Spring JDBC
Execute query:
String query = "select * from device where status = 2 and cinema_code = 'AL10' and content_profile = 'signage'";
List<Device> devices = jdbcTemplate.queryForObject(
query, new Object[] { }, new DeviceRowMapper());
Mapper can look like this:
public class DeviceRowMapper implements RowMapper<Device> {
#Override
public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
Device device = new Device();
device.setId(rs.getInt("ID"));
...
return device;
}
}
How to config the connection in providing url
However as it was mentioned in comments. It is better not to concatenate string parameters.
Your query building can be done in that way.
String query = "select * from device where";
List parameters = new ArrayList();
boolean wasParameter = false;
if(status != null) {
query += " status = ? ";
parameters.add(status);
wasParameter = true;
}
if(cinema != "") {
query += (wasParameter ? " and ": "") +" cinema_code = ? ";
parameters.add(cinema);
wasParameter = true;
}
if(content_profile != "") {
query += (wasParameter ? " and ": "") +" content_profile = ? ";
parameters.add(content_profile);
wasParameter = true;
}
if(mac != "") {
query += (wasParameter ? " and ": "") +" mac = ? ";
parameters.add(mac);
}
Object[] array = parameters.toArray(new Object[0]);
And execute query:
List<Device> devices = jdbcTemplate.queryForObject(
query, array, new DeviceRowMapper());
Assuming that you have configured the Spring datasource you can execute a Spring native query using:
EntityManager em = emf.createEntityManager();
List<Object> results = em.createNativeQuery(query);
You should also update your query, because you can easily get a SQLException when status is null. If it happens you will have an invalid query:
select *
from device
where and cinema_code = 'AL10' and content_profile = 'signage'
Try to use this initial query:
"select * from device where 1=1 "
Using the above, the query will be correct no matter if the first if is executed or no ifs executed at all.

return class hibernate with parameters string and bigdecimal

How can return correctly this query with hibernate?
Help me please
#Override
public UsuarioValido validarUserLoggin(String loggin, BigDecimal canal) throws Exception{
Query q = sessionFactory.getCurrentSession().createSQLQuery("SELECT A.ID_USER, '' AS nombre_canal_canales, A.CANAL_ID, '' AS nombre_pto_vta_puntos_de_venta, "
+ " A.PUNTO_VTA_ID, A.LOGGIN, A.PASSWORD, A.NOMBRES, A.APELLIDOS, A.SN_CAMBIO_PASS, A.ULTINGRESO, A.ULTCMBCONT, A.ESTADO, A.CONTINTENTOS, "
+ " B.NU_INT_PER AS NRO_INT_PASS, A.EMAIL, B.NDIASINACT AS DIAS_VENC_CLAV "
+ " FROM "+General.Esquema_DB+".SEG_USER A "
+ " LEFT JOIN "+General.Esquema_DB+".SEGPOLSEG B ON A.ID_USER = B.ID "
+ " WHERE A.LOGGIN = '"+loggin+"' AND A.CANAL_ID = "+canal);
List rs = q.list();
List<UsuarioValido> validos = q.list();
for (UsuarioValido usuarioValido : validos) {
System.out.println(usuarioValido.toString());
}
UsuarioValido max = (UsuarioValido)rs.get(0);
return max;
}
I usually do it here:
List<UsuarioValido> rs = q.list();
I think this is the best way to do it and not error prone. But do make sure that the query you are using sends back only that class and not a field of that class or results obtained from count(), avg() etc.
But since you are fetching fields you won't be able to use that.
In Hibernate it is recommended to bring back the results in form of List of particular classes and not use Select ...

Hibernate equivalent of getTimestamp() and getInt()

I am currently using ResultSet but want to switch over to Hibernate queries.
I have this code:
Statement stmt = nfCon.createStatement();
stmt = nfCon.createStatement();
ResultSet foo = stmt.executeQuery(sql);
String str = " " + foo.getTimestamp("time").getTime() + ", " + foo.getInt("len");
How can I change it if I am using
Query query = session.createQuery(hql);
List<String> list = query.list();
Obviously, I can't do list.getTimestamp("time");. My SQL/HQL is a select statement. Any help would be appreciated!
select xxx as time, yyy as len from zzz where ...
List<Object[]> list = query.list();
for (Object[] row : list) {
Date date = (Date) row[0];
int len = ((Number) row[1]).intValue();
String str = " " + date.getTime() + ", " + len;
}
This is a general solution. If len is a mapped integer field of an entity, then you can cast it directly to int (or better Integer, especially if it is nullable).
You might also want to look at constructor invocation from HQL, as it could help reduce the boilerplate code involved when representing projected columns as Object arrays.

How to add dynamically an object to a hibernate query

When I use Hibernate query language, how can I add dinamically the object I want to get from the DB?
What I want to reach is somethin like this:
......
if(....){
queryString = "from '" + Object1+ "'";
}
if(...){
queryString = "from '" + Object2+ "'";
}
....
Session session = this.getSessionFactory().getCurrentSession();
Query query = session.createQuery(queryString);
......
I tried different kind of syntax but I get errors every time.
Via Criteria API you can easily build dynamic query's...
Criteria criteria = session.createCriteria(Sale.class);
if (startDate != null) {
criteria.add(Expression.ge("date",startDate);
}
if (endDate != null) {
criteria.add(Expression.le("date",endDate);
}
List results = criteria.list();
you can use this:
......
if(....){
queryString = "from '" + Object1.getClass().getName()+ "'";
}
if(...){
queryString = "from '" + Object2.getClass().getName()+ "'";
}
....
Session session = this.getSessionFactory().getCurrentSession();
Query query = session.createQuery(queryString);
......
What actually you need is to pass class name. You can use following way to get class name of a given object.
object1.getClass().getSimpleName()
So in your case you can append this in your query
example :
if(....){
queryString = "from '" + Object1.getClass().getSimpleName()+ "'";
}

Spring Like clause

I am trying to use a MapSqlParameterSource to create a query using a Like clause.
The code is something like this. The function containing it receives nameParam:
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE :pname ";
String finalName= "'%" +nameParam.toLowerCase().trim() + "%'";
MapSqlParameterSource namedParams= new MapSqlParameterSource();
namedParams.addValue("pname", finalName);
int count= this.namedParamJdbcTemplate.queryForInt(namecount, namedParams);
This does not work correctly, giving me somewhere between 0-10 results when I should be receiving thousands. I essentially want the final query to look like:
SELECT count(*) FROM People WHERE LOWER(NAME) LIKE '%name%'
but this is evidently not happening. Any help would be appreciated.
Edit:
I have also tried putting the '%'s in the SQL, like
String finalName= nameParam.toLowerCase().trim();
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE '%:pname%' "
;
but this does not work either.
You don't want the quotes around your finalName string. with the named parameters you don't need to specify them. This should work:
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE :pname ";
String finalName= "%" + nameParam.toLowerCase().trim() + "%";
MapSqlParameterSource namedParams= new MapSqlParameterSource();
namedParams.addValue("pname", finalName);
int count= this.namedParamJdbcTemplate.queryForInt(namecount, namedParams);
This solution worked for me. I put the "%" on the Object[] parameters list:
String sqlCommand = "SELECT customer_id, customer_identifier_short, CONCAT(RTRIM(customer_identifier_a),' ', RTRIM(customer_identifier_b)) customerFullName "
+ " FROM Customer "
+ " WHERE customer_identifier_short LIKE ? OR customer_identifier_a LIKE ? "
+ " LIMIT 10";
List<Customer> customers = getJdbcTemplate().query(sqlCommand, new Object[] { query + "%", query + "%"}, new RowMapper<Customer>() {
public Customer mapRow(ResultSet rs, int i) throws SQLException {
Customer customer = new Customer();
customer.setCustomerFullName(rs.getString("customerFullName"));
customer.setCustomerIdentifier(rs.getString("customer_identifier_short"));
customer.setCustomerID(rs.getInt("customer_id"));
return customer;
}
});
return customers;
Have you tried placing the % wild cards in your sql string (not the bind variable value itself):
String finalName= nameParam.toLowerCase().trim();
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE '%:finalName%'";
We can use simple JdbcTemplate instead of NamedParamJdbcTemplate
String namecount = "SELECT count(*) FROM People WHERE LOWER(NAME) LIKE ? ";
String finalName= "%" +nameParam.toLowerCase().trim() + "%"; //Notes: no quote
getJdbcTemplate().queryForInt(namecount, new Object[] {finalName});
Hope it helpful for someone using JdbcTemplate

Categories

Resources