Problem using generics in function - java

I have this functions and need to make it one function. The only difference is type of input variable sourceColumnValue. This variable can be String or Integer but the return value of function must be always Integer.
I know I need to use Generics but can't do it.
public Integer selectReturnInt(String tableName, String sourceColumnName, String sourceColumnValue, String targetColumnName) {
Integer returned = null;
String query = "SELECT "+targetColumnName+" FROM "+tableName+" WHERE "+sourceColumnName+"='"+sourceColumnValue+"' LIMIT 1";
try {
Connection connection = ConnectionManager.getInstance().open();
java.sql.Statement statement = connection.createStatement();
statement.execute(query.toString());
ResultSet rs = statement.getResultSet();
while(rs.next()){
returned = rs.getInt(targetColumnName);
}
rs.close();
statement.close();
ConnectionManager.getInstance().close(connection);
} catch (SQLException e) {
System.out.println("Заявката не може да бъде изпълнена!");
System.out.println(e);
}
return returned;
}
// SELECT (RETURN INTEGER)
public Integer selectIntReturnInt(String tableName, String sourceColumnName, Integer sourceColumnValue, String targetColumnName) {
Integer returned = null;
String query = "SELECT "+targetColumnName+" FROM "+tableName+" WHERE "+sourceColumnName+"='"+sourceColumnValue+"' LIMIT 1";
try {
Connection connection = ConnectionManager.getInstance().open();
java.sql.Statement statement = connection.createStatement();
statement.execute(query.toString());
ResultSet rs = statement.getResultSet();
while(rs.next()){
returned = rs.getInt(targetColumnName);
}
rs.close();
statement.close();
ConnectionManager.getInstance().close(connection);
} catch (SQLException e) {
System.out.println("Заявката не може да бъде изпълнена!");
System.out.println(e);
}
return returned;
}

No you don't need to use generics for this.. generic should be used when your supported Types can be to many and you don't know about them before hand and they share something common in them.
Only for just two Types Generics is not a good choice. Using objects can be a better choice.
May be i will say you don't even need to merge these functions, that's what polymorphism is for. keeping things discreet will allow more readability of code

No need to use generic, you can just use Object as the variable type for the function :
public Integer selectIntReturnInt(String tableName, String sourceColumnName, Object sourceColumnValue, String targetColumnName) {
Integer returned = null;
String query = "SELECT "+targetColumnName+" FROM "+tableName+" WHERE "+sourceColumnName+"='"+sourceColumnValue.toString()+"' LIMIT 1";
try {
Connection connection = ConnectionManager.getInstance().open();
java.sql.Statement statement = connection.createStatement();
statement.execute(query.toString());
ResultSet rs = statement.getResultSet();
while(rs.next()){
returned = rs.getInt(targetColumnName);
}
rs.close();
statement.close();
ConnectionManager.getInstance().close(connection);
} catch (SQLException e) {
System.out.println("Заявката не може да бъде изпълнена!");
System.out.println(e);
}
return returned;
}

You don't need to use generics. Just declare it as
public Integer selectReturnInt(String tableName,
String sourceColumnName,
Object sourceColumnValue,
String targetColumnName) {
...
}

For the love $deity please don't use dynamic SQL. You will get injection vulnerabilities.
You want to break this into (at least) three method. One with the bulk of the implementation, and one each for the different types.
Also of note:
Resource handling should be of the form final Resource resource = acquire(); try { ... } finally { resource.release(); }, or in JDK7 try (final Resource resource = acquire()) { ... }.
Singletons are the work of the devil.
Exception handling considered a good idea, whereas sinking to a printf is bad.
You're probably better off only returning a value if there is exactly one result set and throwing an exception otherwise.

Have the second method just call the first:
public Integer selectIntReturnInt(String tableName, String sourceColumnName, Integer sourceColumnValue, String targetColumnName) {
return selectReturnInt(tableName, sourceColumnName, sourceColumnValue.toString(), targetColumnName);
}

Related

How do I turn my INT (id) into a String in my return from MySQL?

I'm trying to my a very simple webapplication, webshop, for cupcakes.
From the webApp you can choose a cupcake form the dropdown with three attributes
(top, bottom, quantity). These are stored in an ArrayList on my sessionScope but all in numbers e.g. Chokolate as 1 and Vanilla as 2. I want to use these topId numbers to ask my DB (MySQL) for what is in 1 and then have it return Chokolate.
I think I am almost there with my code, but can't get it to return my String, as my topId is an Int.
public static Top getTopById(int topId) {
readFromArrayPutInSQL();
String sql = "INSERT INTO cupcaketopping (toppingType, toppingPrice) VALUES (?, ?)";
try {
ConnectionPool connectionPool = new ConnectionPool();
String query = "SELECT toppingType FROM cupcaketopping";
Statement statement = connectionPool.getConnection().createStatement();
ResultSet rs = statement.executeQuery(query);
rs.getString(topId);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return topId; //Here is the problem - I GUESS?
}
Code after changes due to input in comments, seem to be working!
public static Top getTopById(int topId) {
readFromArrayPutInSQL();
String query = "SELECT toppingType FROM cupcaketopping WHERE toppingID = "+topId+"";
try {
ConnectionPool connectionPool = new ConnectionPool();
PreparedStatement preparedStatement = connectionPool.getConnection().prepareStatement(query);
ResultSet rs = preparedStatement.executeQuery(query);
rs.next();
return new Top(rs.getString(1));
//connectionPool.close(); //NOTE! Won't run, IntelliJ is asking me to delete!
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
There are a few problems:
You're selecting all rows from the cupcaketopping table, regardless of the topId. You should probably be using a PreparedStatement, and then use topId as part of your query.
You never call ResultSet#next(). The result set always starts "before" the first row. You have to call next() for each row in the result set (it returns true if there is a row to read).
The ResultSet#getString(int) method gets the String value of the column at the given index of the result. You only select one column, so the argument should probably be 1 (not topId).
You never close the Statement when done with it.
Depending on how your connection pool class works, you might actually need to close the Connection instead.
You never try to use the String returned by rs.getString(topId).
You never try to convert the query result to a Top instance.
Given it's possible the query will return no result, you might want to consider making the return type Optional<Top>.
The sql string seems to have no purpose.
Your code should look more like this:
public Optional<Top> getTopById(int topId) {
Connection conn = ...;
String query = "SELECT toppingType FROM cupcaketopping WHERE id = ?";
// closes the statement via try-with-resources
try (PreparedStatement stat = conn.prepareStatement(query)) {
stat.setInt(1, topId);
ResultSet rs = stat.executeQuery();
// assume unique result (as it's assumed the ID is the primary key)
if (rs.next()) {
// assumes 'Top' has a constructor that takes a 'String'
return Optional.of(new Top(rs.getString(1)));
} else {
return Optional.empty();
}
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
Your actual implementation may vary, depending on how the rest of your code is designed.

I am getting error on "If(rs.next())" and ".getString"

I am getting error in if(rs.next()) and .getString on my code. This is my code
public void keyPressed(KeyEvent e) {
Function f = new Function();
Result rs = null;
String ans = "Key";
rs = f.find(jTextField1.getText());
try{
if(rs.next()){
jTextArea1.setText(rs.getString("Key"));
}
}catch(Exception ex){
}
}
OK the methods next() and getString() are parts of the java.sql.ResultSet interface. Your code should look like this:
public void keyPressed(KeyEvent e) {
Function f = new Function();
ResultSet rs = null;
String ans = "Key";
rs = f.find(jTextField1.getText());
try{
if(rs.next()){
jTextArea1.setText(rs.getString("Key"));
}
}catch(Exception ex){}
}
And if the Function objects method find(String search) returns a valid java.sql.ResultSet implementation, you can use next() to move pointer to next Result and to check if it has one. And then you can easyly use getString(String columnName) to get the value of a column as String.
I would return ResultSet in an method like this. Let your Function class method find directly return your desired value or null or empty string. Handling the ResultSet here isn't good practice. Keep your concerns together.

Printing a query from a database

I am trying to access a database and print off a query.
I am trying to access a DEVICE table and print off the DEVICE_ID, but i am unsuccessful so far.
Here is my code at the moment;
public static void main(String[] args) throws FileNotFoundException {
try {
Class.forName("org.hsqldb.jdbc.JDBCDriver");
Preferences sysRoot = Preferences.systemRoot();
Preferences prefs = sysRoot.node("com/davranetworks/zebu");
url = prefs.get("dburl", "jdbc:hsqldb:E:\\eem\\eemdb");
} catch (Exception e) {
e.printStackTrace();
}
Connection c = getConnection();
try {
c.setAutoCommit(true);
Statement s = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = s.executeQuery("SELECT * FROM eem_db.device");
ResultSet deviceId = s.executeQuery("select device_id from eem_db.device");
System.out.println(deviceId);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection c = null;
try {
c = DriverManager.getConnection(url);
} catch (SQLException e) {
System.out.println("Error initialising connection" + e);
}
return c;
}
The returned value is org.hsqldb.jdbc.JDBCResultSet#1d3d68df.
I don't know what this value relates to as I was expecting 3 integer values.
Can anyone help me on this?
You have to iterate over the rows contained in the ResultSet and for each row get the column you want:
ResultSet deviceIdRS = s.executeQuery("select device_id from eem_db.device");
while(deviceIdRS.next()) {
System.out.println(deviceIdRS.getString("device_id"));
}
You must use the ResultSet getXXX method that correspond with your column type, for example, getInt, getString, getDate...
That ResultSet deviceId is actually an object contains rows of result from your sql, so you only can see the memory address when you print it out.
You need something like:
while(deviceId.next()){
System.out.print(deviceId.getInt(1));
}
s.executeQuery("select device_id from eem_db.device"); is returning a resultSet, you must find out the value from result set.
like
int device_id = resultset["deviceId"];
while (deviceId.next())
{
// Printing results to the console
System.out.println("device_id- "+ deviceId.getInt("device_id");
}
iterate object using resultset.
You are printing object of ResultSet, it won't give you the right values.
You need to iterate the loop like below
while(deviceId.next()) {
int integerValue = deviceId.getInt(1);
System.out.println("content" + integerValue)
}
deviceId.close();
s.close();

java how retrieve data from database

I have code
public static String getData(String query) {
String output = "";
try {
String connectionUrl = "jdbc:sqlserver://localhost:1234;databaseName=123;user=123;password=123";
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
con = DriverManager.getConnection(connectionUrl);
String SQL = "select smth from tableName where smth";
stmt = con.createStatement();
rs = stmt.executeQuery(query);
while (rs.next()) {
output = (String) rs.getObject(1);
}
rs.close();
}
catch (Exception e) {
return "ERROR while retrieving data: " + e.getMessage();
}
return output;
}
It works if value is string. But if it integer? Or boolean? How to modify this method so it would be universal, no matter what type data I get I still return it as string?
First retreive the result in ResultSet rs,
then you can write the code like below.
You can check the instance of the object and than assign the value.
String str;
Object obj = (Object)rs.getObject(1);
if(obj instanceof String){
//do you work here for string like below
str=(String)obj;
}
else if (obj instanceof Integer){
//do your work for Integer
}
// same you can do for other types
in this line
output = (String) rs.getObject(1);
if string then use
output = rs.getString(1);
if int
output = rs.getInt(1);
click oracle for more info
You can't accurately do that without using ResultSetMetaData class to get the column type.
Get the column data according to the type of the column.
You are getting the value from the resultset presuming that it is always a String and trying to typecast the Object instance. You should make use of the retrieve methods based on the type. Most of the cases, we will be knowing the datatype of the column values from which we retried the data. You can write the program based on the column's type. that's why ResultSet API has a method for each datatype.
For String
rs.getString(1);
For Int
rs.getInt(1)
Please read the documentation of ResultSet
while (rs.next())
{
String[] data;
data = new String[100];
data[i] = rs.getString("smth");
i = i + 1;
}
Try this you got your data in array.. use array instead of object.
what about toString()?
while (rs.next()) {
output = rs.getObject(1).toString();
}

Using PreparedStatement template issue

Here's my static utility:
//String sqlQuery = "select count(name) as num from tbname where name = ?"
//String name = "testString";
private static int correct(Connection connection, String sqlQuery, String name) {
int result = 0;
PreparedStatement statatement = null;
ResultSet rs = null;
try {
statatement = connection.prepareStatement(sqlQuery);
statatement.setString(1, name);
rs = statatement.executeQuery();
while (rs.next()) {
result = rs.getInt("num");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
rs.close();
statatement.close();
} catch (SQLException e) {
throw new RuntimeException(e.getMessage());
}
return result;
}
}
The method above returns 0 (incorrect result), but the following one returns '1' (it works OK, it the same sql query):
//String sqlQuery = "select count(name) as num from tbname where name = 'testString'"
private static int correct(Connection connection, String sqlQuery, String name) {
int result = 0;
PreparedStatement statatement = null;
ResultSet rs = null;
try {
statatement = connection.prepareStatement(sqlQuery);
rs = statatement.executeQuery();
while (rs.next()) {
result = rs.getInt("num");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
rs.close();
statatement.close();
} catch (SQLException e) {
throw new RuntimeException(e.getMessage());
}
return result;
}
}
Could you please give me any advise, so I could resolve the problem.
PS: I'm not sure if it does matter, but the actual streetName - has a name in windows-1251 encoding (Russian) text.
PPS: The database is Oracle 10.
It might be a character set issue. According to the Oracle JDBC Drivers release 10.1.0.2.0 (10g) README:
The following is a list of known
problems/limitations:
If the database character set is AL32UTF8, you may see errors under the
following circumstances:
accessing LONG and VARCHAR2 datatypes.
binding data with setString() and setCharacterStream().
So if your database character set is AL32UTF8, you might have to get it changed to something else.
Also, what is the datatype of your column? VARCHAR2?
It seems the encoding conflict with the one which you set in your DB encoding charset and the the String you are passing..
You can do these 2 tries
Set the DB encoding to UTF-8 and then give a try. If this does not work you may go with following 2nd option
Set DB encoding charset to UTF-8 and also set the String by using this String constructor String(byte[] bytes, String charsetName)

Categories