Hibernate equivalent of getTimestamp() and getInt() - java

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.

Related

Column result doesn't as be expected

Here i have query to join two table and merge it into one result by using this query
String query = "SELECT * FROM tb_barang RIGHT JOIN tb_jenis ON tb_barang.kd_jenis = tb_jenis.kd_jenis ";
And here is my table structures for both of tables
Table "tb_barang"
https://i.stack.imgur.com/6OpeC.png
And Table "tb_jenis"
https://i.stack.imgur.com/UhLty.png
I was expecting the output like this
https://i.stack.imgur.com/zhtHx.png
However, when I take column "jenis", java throw exception into it because either out of range or column not found.
Then i check whether the column is exist or not using :
ResultSet resTabel = new mysqlDriver().getKolomBarangList();
ResultSetMetaData metaData = resTabel.getMetaData();
int colCount = metaData.getColumnCount();
if (resTabel.next()) {
for (int i = 1; i <= colCount; i++) {
System.out.println("Col(" + i + ") '" + metaData.getColumnName(i) + "' value:" + resTabel.getString(i));
}
The output:
Col(1) 'kd_barang' value:BAR0000
Col(2) 'nama_barang' value:A
Col(3) 'kd_jenis' value:J_1
Col(4) 'jumlah_barang' value:1
Col(5) 'harga_satuan' value:1
BUILD SUCCESSFUL (total time: 35 seconds)
How to achieve this? Thanks for response
Apparently, i was miss type the method name thanks to #forpas. the getKolomBarangList() refer to field name of table tb_barang and not executing "JOIN" clauses
protected ResultSet getBarangList()throws SQLException, NullPointerException, ClassNotFoundException{
String query = "SELECT * FROM tb_barang RIGHT JOIN tb_jenis ON tb_barang.kd_jenis = tb_jenis.kd_jenis ";
if(resForListBarang == null){
resForListBarang = alwaysDoResultSet(query);
}
return resForListBarang;
}
protected ResultSet getKolomBarangList() throws SQLException, Exception{
String query = "SELECT * FROM tb_barang";
if(getBarangKolom == null){
getBarangKolom = alwaysDoResultSet(query);
}
return getBarangKolom;
}
And the output for getBarangList() was expected as the final result
Col(1) 'kd_barang' value:BAR0000
Col(2) 'nama_barang' value:A
Col(3) 'kd_jenis' value:J_1
Col(4) 'jumlah_barang' value:1
Col(5) 'harga_satuan' value:1
Col(6) 'kd_jenis' value:J_1
Col(7) 'jenis' value:Pakan Hewan
BUILD SUCCESSFUL (total time: 21 seconds)
Thanks to anyone who helping me out :)

JDBC dynamic query, only put value to string if not -1

I have a problem with JDBC and java.
I have a Query like this:
String updateSql = "UPDATE league SET season=?, playedMatches=?, percentHomeWins=?, percentDraws=?, percentAwayWins=?, averageGoalsPerGame=?, averageGoalsHomePerGame=?, averageGoalsAwayPerGame=?, percentOverOne=?, percentOverTwo=?, percentOverThree=?, percentBothTeamsScored=?, scoredGoalsTotal=? " + whereClause + " and country='" + l.getCountry() + "'";
all values after "season" can either be a number >= 0 or -1. -1 means, that there is no value. the values come from a class that holds data (like an object model).
I want only the values in my query, which are >= 0. The other one should not be in the query, because they replace data in the database, which they should not.
Can anyone help me archiving this?
Use a StringBuilder to dynamically build the SQL statement, e.g.
StringBuilder sql = new StringBuilder("UPDATE league SET season=?");
List<Integer> numValues = new ArrayList<>();
if (l.getPlayedMatches() != -1) {
sql.append(", playedMatches=?");
numValues.add(l.getPlayedMatches());
}
if (l.getPercentHomeWins() != -1) {
sql.append(", percentHomeWins=?");
numValues.add(l.getPercentHomeWins());
}
// ... more code ...
sql.append(whereClause)
.append(" and country=?");
try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) {
int paramIdx = 0;
stmt.setInt(++paramIdx, l.getSeason());
for (Integer numValue : numValues)
stmt.setInt(++paramIdx, numValue);
stmt.setString(++paramIdx, l.getCountry());
stmt.executeUpdate();
}

MYSQL+Hibernate, Query cannot be created

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);.

JdbcTemplate does not support Parameterized Query 'IN' case? Must by NamedParameterJdbcTemplate?

Aimed at preventing SQL injection attacks, all the SQL Statement code in my project should transformed to Parameterized Query. But I got a problem when the query condition includes a 'IN' case. Like this (Using DB2 database):
String employeeId = 'D2309';
String name = "%brady%";
List<Integer> userRights = new ArrayList<Integer>();
userRights.add(1);
userRights.add(2);
userRights.add(3);
String sql = "SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ? AND NAME LIKE ?
AND RIGHT IN (?)";
jdbcTemplate.query(sql, new Object[] {employeeId, name, userRights}, new
EmployeeRowMapper());
The above code runs failed with the exception:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad
SQL grammar [SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ? AND NAME LIKE ? AND
RIGHT IN (?)]; nested exception is com.ibm.db2.jcc.am.io: [jcc][1091][10824]
[3.57.82] .... ERRORCODE=-4461, SQLSTATE=42815
The question here is that does not JdbcTemplate support Parameterized Query for IN case? and I know this work can be done by NamedParameterJdbcTemplate, and whether only NamedParameterJdbcTemplate can do IN case query?
Thanks a lot.
As I already mentioned in the comments, I'm not happy with this solution as it dynamically generates a number of SQL statements. Given the number of userRights is between 1 and n, it requires up to n prepared statements in the cache.
The below should work (I did not try it).
String employeeId = 'D2309';
String name = "%brady%";
List<Integer> userRights = new ArrayList<Integer>();
userRights.add(1);
userRights.add(2);
userRights.add(3);
// build the input string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < userRights.size; i++) {
sb.append("?");
if (i < userRights.size() - 1) {
sb.append(", ");
}
}
// build the SQL
String sql = "SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ?" +
" AND NAME LIKE ?" +
" AND RIGHT IN (" + sb.toString() + ")";
// init the object array
// size is employeeId + name + right
Object[] param = new Object[2 + userRights.size()];
// fill it
param[0] = employeeId;
param[1] = name;
for (int i = 0; i < userRights.size(); i++) {
param[i + 2] = userRights.get(i);
}
jdbcTemplate.query(sql, param, new EmployeeRowMapper());

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