I was performing JDBC select query in my web service to return some values from my database. Part of this table is attached to this question. After performing following query:
SELECT * FROM uses WHERE uses_user_fk='22';
I receive only one row, but in database are two values that meet the query conditions, as you can see in attached picture. Can anyone tell me where I made a mistake. I’m using following JDBC instruction to execute the query
ResultSet tempResultSet = statement.executeQuery(query);
Bellow image of database table uses:
Below the compete method that query the database, argument query is the same as listed earlier “SELECT * FROM uses…”. I should add that the answer for that query is 4, I also try this query without using quotes (uses_user_fk=22) but the result was the same:
protected ArrayList<Integer> queryForIds(String query, String column) throws Exception {
ArrayList<Integer> ids = new ArrayList<>();
try {
Class.forName("com.mysql.jdbc.Driver");
connect = DriverManager
.getConnection(GeneralDatabaseConstants.DATABASE_CONNECTION_URL);
statement = connect.createStatement();
ResultSet tempResultSet = statement.executeQuery(query);
if (tempResultSet.next())
ids.add(new Integer(tempResultSet.getInt(column)));
} catch (Exception e) {
throw e;
} finally {
close();
}
return ids;
}
replace
if (tempResultSet.next())
with
while (tempResultSet.next())
Related
I'm trying to do a select count query in Sql Server using Dapper. The expected response should be 0 when a profile does not exist. When I do the query in SSMS it returns correctly, but in the API using Dapper it returns 1. Any idea why this is happening?
public IActionResult GetProfileCount(string profileId)
{
int profileCount = 0;
using (IDbConnection db = new SqlConnection(connectionString))
{
try
{
profileCount = db.Query($"select count(*) from Profile where Id='{profileId}'").Count();
}
catch(Exception ex)
{
Console.WriteLine($"Error retrieving count for ProfileId: {profileId}", ex.Message);
}
}
return Ok(profileCount);
}
I see you added your own answer but could I recommend not doing it that way. When you do
profileCount = db.Query($"select * from Profile where Id='{profileId}'").Count();
What you are actually doing is selecting every field from the database, pulling it into your C# application, and then counting how many results you got back. Then you are binning all that data you got back, very inefficient!
Change it to this :
profileCount = db.QueryFirst<int>($"select count(*) from Profile where Id = #profileId", new { profileId })");
Instead you are selecting an "int" from the result set, which just so happens to be your count(*). Perfect!
More on querying in Dapper here : https://dotnetcoretutorials.com/2019/08/05/dapper-in-net-core-part-2-dapper-query-basics/
Also notice that (similar to the other answer), I am using parameterized queries. I also heavily recommend this as it protects you from SQL Injection. Your initial example is very vulnerable!
You can read a little more about SQL Injection in C#/MSSQL here https://dotnetcoretutorials.com/2017/10/11/owasp-top-10-asp-net-core-sql-injection/ But just know that Dapper protects you from it as long as you use the inbuilt helpers to add parameters to your queries.
Another option is use the method ExecuteScalar for "select count" queries:
profileCount = db.ExecuteScalar<int>("select count(*) from Profile where Id=#profileId", new { profileId });
Ref.: https://www.learndapper.com/selecting-scalar-values
Try and change your query to the following:
db.Query($"select count(*) from Profile where Id = #ProfileId", new { ProfileId = profileId }).Count()
I figured it out. The .Count() is counting the rows of the result, which is going to be 1 because the result is one row displaying the number 0. I switched my code to this and it works now.
public IActionResult GetProfileCount(string profileId)
{
int profileCount = 0;
using (IDbConnection db = new SqlConnection(connectionString))
{
try
{
profileCount = db.Query($"select * from Profile where Id='{profileId}'").Count();
}
catch(Exception ex)
{
Console.WriteLine($"Error retrieving count for ProfileId: {profileId}", ex.Message);
}
}
return Ok(profileCount);
}
I have a select Oracle SQL that I am hitting using jdbcTemplate.query method. This returns a bean of the values from the table. I am passing a dynamic value to the query that will be used in the WHERE clause. However, the SQL values for few values that i am passing. But when I pass the value as NA it won't work. Any suggestions on this or help me with what am i missing?
private static final String regionSearchSql = "SELECT PRFLID, PRFLNM, RGN_CD FROM %PREFIX%MER_PRFL WHERE RGN_CD = ?";
public List<SearchProfileBean> regionSearchProfile(SearchProfileRequest searchProfileRequest) throws DatabaseQueryException {
try {
return jdbcTemplate.query((QueryUtility.getQueryWithPrefix(regionSearchSql,prefix)), new SearchProfileRowMapper(), searchProfileRequest.getRegionName());
} catch (Exception e) {
throw new DatabaseQueryException(QueryUtility.getQueryWithPrefix(regionSearchSql, prefix), e);
}
}
If i pass 'EMEA', 'LAC', 'JAPA' in searchProfileRequest.getRegionName() - the SQL returns perfect results. But if I pass 'NA' in searchProfileRequest.getRegionName(), it gives empty results. But there are rows in the table for NA.
I run an insert statement using Apache DBUtils. However, I am not sure why I have to include ResultSetHandler for this case:
String theQuery = QueryGenerator.insertintoStats();
ResultSetHandler<Object> dummyHandler = new ResultSetHandler<Object>() {
#Override
public Object handle(ResultSet rs) throws SQLException
{
return null;
}
};
try
{
queryRunner.insert(connection, theQuery, dummyHandler, Constants.UUIDSTR.toString(), name, prevbackupTime,
curbackupTime, updStartTime, delStartTime, bkupType.toString(), rowCount);
}
catch (SQLException e)
{
LOGGER.info(theQuery.toString());
LOGGER.error("Caught exception!", e);
}
Similar's the case for insertbatch which does use ResultSetHandler. I have resorted to use batch call for batch queries. Can anyone explain why we would be needing resultset handler for insert?
From documentation https://commons.apache.org/proper/commons-dbutils/apidocs/:
public <T> T insert(String sql,
ResultSetHandler<T> rsh,
Object... params)
throws SQLException
rsh - The handler used to create the result object from the ResultSet
of auto-generated keys.
If you insert values in a table which generate id upon insertion, you can retrieve it back, for example see this answer how to do this manually : https://stackoverflow.com/a/1915197/947111
You need ResultSetHandler<T> rsh to iterate over ResultSet which returned with id's which has been created.
i use struts2 and hibernate jpa for my app and i have an error when traying using update query with hibernate
here is my code :
in my class dao
#Override
public void UpdateNoteEvaluation() {
try {
String hql="update Evaluation e " +
"SET e.Eval_NoteGlobal =: ( SELECT SUM( sv.SousEval_Note ) AS sum FROM sousevaluation sv )" +
"ORDER BY EVAL_ID DESC LIMIT 1 ";
Query q= session.createQuery(hql);
q.executeUpdate();
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
}
}
in my class Action :
public String saveOrUpdate(){
sousevaldao.UpdateNoteEvaluation();
System.out.println("update note ok ok");
return SUCCESS;
}
so here i can't make the update i get this error :
java.lang.IllegalArgumentException: node to traverse cannot be null!
at org.hibernate.hql.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:55)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:277)
knowing i have test the update query im phpmyadmin it's work fine
If query has been tested to be working one via phpMyAdmin, it is quite clear that query is SQL query - not a HQL query. Also syntax of query seems to contain MySQL SQL dialect specific LIMIT clause.
Query for native SQL queries can be created via Session.createSQLQuery(String queryString) method:
String sql = ...
Query q = session.createSQLQuery(sql);
EDIT
After staring at this for 2 days, I do see one issue. I was still opening the original connection. So I changed the inner open statements to conn2.Open. Then, I changed the second inner query to where all the variables were number 3 instead of 2 so that they were completely different than the previous query. At that point, I got the error:
There is already an open DataReader associated with this Command which must be closed first.
I took out the inner connections, thinking I could use the outer connection and took out the inner .Close lines, but that also returned an error saying the connection was not closed.
END EDIT
I am writing a script that updates user information with data pulled from other tables where that user may be in it multiple times for purchases made.
So first, the "outside" sql query pulls some data from the items table which contains purchaser information as well as category information. For each item, it is going to check it's purchaser's information.
Second, the first "inner" sql query pulls category information from the user table. Some code is then run to see if they're already marked as purchasing from the category of the "outside" query. If they are not, it adds the category to a string variable.
Lastly, the second "inner" sql query updates the user table for the current user with the new category list.
I've asked about how to perform queries like this before, but was always given a solution of combining the queries into one. That worked for the other queries, but I cannot do that here. I must iterate through each record of the outer query to perform the necessary functions inside of it. But my issue here is that I get an SQL error saying that the connection was not closed, and it points to the catch of the outer query (for 'conn').
I had tried to set my 2 inner queries so that they used different connection variables (conn2 and conn3), and also different strSQL variables, but that didn't help. And I'm still a newb when it comes to SQL, having programmed using MySQL until this probject. Any help would be greately appreciated.
using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["connectionName"].ToString()))
using (SqlCommand strSQL = conn.CreateCommand())
{
strSQL.CommandText = "SELECT field FROM itemsTable";
try
{
conn.Open();
using (SqlDataReader itemReader = strSQL.ExecuteReader())
{
while (itemReader.Read())
{
{Do some stuff here}
using (SqlConnection conn2 = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["connectionName"].ToString()))
using (SqlCommand strSQL2 = conn2.CreateCommand())
{
strSQL2.CommandText = "SELECT fields FROM userTable";
try
{
conn2.Open();
using (SqlDataReader itemReader2 = strSQL2.ExecuteReader())
{
while (itemReader2.Read())
{
{Do stuff here}
}
itemReader2.Close();
}
}
catch (Exception e3)
{
throw new Exception(e3.Message);
}
finally
{
conn2.Close();
}
}
{Do some more stuff here}
using (SqlConnection conn2 = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["connectionName"].ToString()))
using (SqlCommand strSQL2 = conn2.CreateCommand())
{
strSQL2.CommandText = "UPDATE userTable set field='value'";
try
{
conn2.Open();
strSQL2.ExecuteNonQuery();
}
catch (Exception e2)
{
throw new Exception(e2.Message);
}
finally
{
conn2.Close();
}
}
{Do even more stuff here.}
}
itemReader.Close();
}
}
catch (Exception e1)
{
throw new Exception(e1.Message);
}
finally
{
conn.Close();
}
}
There's some unusual logic going on with conn.Open(). I see it used several times, but I think you mean to use conn2.Open() in the inner using statements after the first call.