Getting an Integer From MySQL Select Statement - java

I would like to get an integer saved in my MySql DB into an Integer in Java. I have a Table, that includes PlayerName and Level. I would like to get The Level (Integer) From a Specific Player. And then Add Integer "Value" to it. Then put it back in the DB. My Code up to now is:
public void addinputPData(String loc, int value, Player player, String playername){
//add input Player Data
try{
logm("Putting Kill Death Int Data into " +player.getName() + "'s Profile!");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/WebCom", "root", "MyPW");
int ovalue = -1;
Statement stmt = (Statement) con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT "+loc+" FROM PlayerData WHERE PlayerName='"+playername+"'");
if(rs.next()){
ovalue= rs.getInt(loc);
}
if(ovalue == -1){
logm("Error Occured");
}
int nvalue = value + ovalue;
String insert = "UPDATE PlayerData SET "+ loc + "='" + nvalue + "' WHERE PlayerName='" + playername + "'";
stmt.executeUpdate(insert);
con.close();
}catch(Exception e){
logm("Could Not Send Data To MYSQL DATABASE SERVER s: "+ e.getMessage());
}
}
I don't know why this won't work, Is there anything obvious that i am missing? Thank you in advance.

So first what you must understand is that when you won't use parametrized statements, there is big danger of SQL Injection. So your code is very dirty written.
So anyway, use PreparedStatement with parametrized SQL statements for much more better performace. Now rewrite your code like this:
final String SELECT_QUERY = "SELECT level FROM PlayerData WHERE PlayerName = ?";
final String UPDATE_QUERY = "UPDATE PlayerData SET level = ? WHERE PlayerName = ?";
public boolean dataMethod(String playerName) {
Connection con = null;
PreparedStatement ps = null;
PreparedStatement ps1 = null;
ResultSet rs = null;
int dataLevel = 0;
try {
// getConnection etc...
ps = con.prepareStatement(SELECT_QUERY);
ps.setString(1, playerName) // first param is order of ? param, starts with 1(not 0)
rs = ps.executeQuery();
while (rs.next()) {
dataLevel = rs.getInt();
}
if (dataLevel > 0) {
ps1 = con.prepareStatement(UPDATE_QUERY);
ps1.setInt(1, dataLevel);
ps1.setString(2, playerName);
ps1.executeUpdate();
}
return true;
}
catch (SQLExcetion ex) {
Logger.getLogger(YourClass.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
finally {
if (con != null) {
con.close();
}
}
}
Step by step, first init your statement, sets parameters if you have then when you use select, you will retrieve data in ResultSet that is table of data generated with query. imlicitly cursor in ResultSet is position before first row so you have to use next() method to go on current row and with the help of getter method you add data from ResultSet to your variable. Then you check if it's correct, if do, init second statement and execute it. And that's all.
But you should consider when you use more that 1 operation, sets autoCommit on false and all operations will do in one Transaction, because implicitly in JDBC is one operation = one transaction. And second, you should consider to use SQL stored procedures for add any data, update data or delete. It's more safer yet and less code. So let database working when it able to do it and also it's faster of course.
At the last, really you should think about this approach and makes your code more safer, faster and cleaner. Not have look on simplicity but on efficiency, compability and security.
More about SQL Injection
And when you decided right to use stored procedure, you can use it like this:
CREATE OR REPLACE PROCEDURE SOME_NAME(VARCHAR v_name PlayerData.name%type)
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
// body
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;
So now you have to create String for call procedure.
final String CALL_SOMENAME = "{call SOME_NAME(?)}";
Then intead of PreparedStatement you have to use CallableStatement that is interface used to execute SQL stored procedures.
cs.prepareCall(CALL_SOMENAME); // Creates a cs object for calling db stored procedures
cs.setString(1, playerName);
cs.execute();
I don't know why many people searching the easiest way to do something and don't look at performance and readability of code.
Regards

In the UPDATE statement, you're inserting the value for the "loc" column as a string (there are single quotes around the value). If the database column is an integer, then this could be causing a problem.
Tip: JDBC provides a class called PreparedStatement. This class allow you to build SQL queries safely. It makes sure that all user input is properly escaped in order to avoid security vulnerabilities.
PreparedStatement ps = con.prepareStatement("UPDATE PlayerData SET " + loc + " = ? WHERE PlayerName = ?");
ps.setInt(1, nvalue);
ps.setString(2, playername);
ps.execute();

Related

java.sql.SQLException: Operation not allowed after ResultSet closed [help] [duplicate]

When I execute the following code, I get an exception. I think it is because I'm preparing in new statement with he same connection object. How should I rewrite this so that I can create a prepared statement AND get to use rs2? Do I have to create a new connection object even if the connection is to the same DB?
try
{
//Get some stuff
String name = "";
String sql = "SELECT `name` FROM `user` WHERE `id` = " + userId + " LIMIT 1;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
name = rs.getString("name");
}
String sql2 = "SELECT `id` FROM `profiles` WHERE `id` =" + profId + ";";
ResultSet rs2 = statement.executeQuery(sql2);
String updateSql = "INSERT INTO `blah`............";
PreparedStatement pst = (PreparedStatement)connection.prepareStatement(updateSql);
while(rs2.next())
{
int id = rs2.getInt("id");
int stuff = getStuff(id);
pst.setInt(1, stuff);
pst.addBatch();
}
pst.executeBatch();
}
catch (Exception e)
{
e.printStackTrace();
}
private int getStuff(int id)
{
try
{
String sql = "SELECT ......;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
return rs.getInt("something");
}
return -1;
}//code continues
The problem is with the way you fetch data in getStuff(). Each time you visit getStuff() you obtain a fresh ResultSet but you don't close it.
This violates the expectation of the Statement class (see here - http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html):
By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects. All execution methods in the Statement interface implicitly close a statment's current ResultSet object if an open one exists.
What makes things even worse is the rs from the calling code. It is also derived off-of the statement field but it is not closed.
Bottom line: you have several ResultSet pertaining to the same Statement object concurrently opened.
A ResultSet object is automatically
closed when the Statement object that
generated it is closed, re-executed,
or used to retrieve the next result
from a sequence of multiple results.
I guess after while(rs2.next()) you are trying to access something from rs1. But it's already closed since you reexecuted statement to get rs2 from it. Since you didn't close it, I beleive it's used again below.

Executing multiple queries with single PS

i have created prepared statement object .
now i want to get the result of multiple queries . is it possible to do using single prepared statement object/ find the piece code below
PreparedStatement ps = null;
String moviedirectorQry = "SELECT movie_director FROM movies WHERE movie_title= ?";
ps = dbConnection.prepareStatement(moviedirectorQry);
ps.setString(1, "Twilight");
ResultSet rs=null;
rs = ps.executeQuery(moviedirectorQry);
while (rs.next()) {
String director_name = rs.getString("movie_director");
System.out.println("director name : " + director_name);
}
now i want to run another query.. how to do
If the idea is to use the same PreparedStatement for different queries of the same type with only parameters' value that change, yes it is possible, simply call clearParameters() first to clear the parameters in case you want to reuse it before setting the new parameters' value.
The code could be something like that:
if (ps == null) {
// The PreparedStatement has not yet been initialized so we create it
String moviedirectorQry = "SELECT movie_director FROM movies WHERE movie_title= ?";
ps = dbConnection.prepareStatement(moviedirectorQry);
} else {
// The PreparedStatement has already been initialized so we clear the parameters' value
ps.clearParameters();
}
ps.setString(1, someValue);
ResultSet rs = ps.executeQuery();
NB: You are supposed to use executeQuery() not ps.executeQuery(moviedirectorQry) otherwise the provided parameters' value will be ignored such that the query will fail.

How to return result sets from Stored Procedure?

I created a Stored Procedure where I can fetch all my data that I inserted in my following textfields. How can I fetch all of this data by calling my Callable Statement? I think this is the easiest way than Batch Statement based on what I read. I only drag and drop this following components just a practice purposes.
Stored Procedure
CREATE PROCEDURE show_data(OUT FULLNAME VARCHAR(50), OUT ADDRESS VARCHAR(50))
PARAMETER STYLE JAVA
LANGUAGE JAVA
READS SQL DATA
DYNAMIC RESULT SETS 1
EXTERNAL NAME 'Frame.searchButton'
I used OUT parameter to retrieve values using getXXX() methods. I'm just little bit confuse since this is my first time to use Stored Procedure in derby.
GUI
After the user search the following record in Database. If the value exist it will print to the designated textfields.
SOURCE CODE
String searchRecord = searchTf.getText();
String searchQuery = "SELECT * FROM SAMPLEONLY";
ResultSet data[] = null;//Why should I use this array?
try (Connection myConn = DriverManager.getConnection(url, user, pass);
PreparedStatement myPs = myConn.prepareStatement(searchQuery);)
{
String addFullname = fullnameTf.getText();//first field
String addAddress = addressTf.getText();//second field
data[0] = myPs.executeQuery();
CallableStatement cs = myConn.prepareCall("{ call showData(?, ?)}");
cs.setString(1, addFullname);
cs.setString(2, addAddress);
boolean hasResults = cs.execute();
if (hasResults) {
ResultSet rs = cs.getResultSet();
while (rs.next()) {
String getFullname = rs.getString(1);//get the value
String getAddress = rs.getString(2);
fullnameTf.setText(getFullname);//set the text here
addressTf.setText(getAddress);
}//end of while
rs.close();//close the resultset
}//end of if
}//end of try
catch (SQLException e)
{
e.printStackTrace();
}
}//end of else
}
After I insert in Search textfields it throws me a error NullPointerExeption. I follow Derby Reference Manual so I can have a guide writing a proper Stored Procedure. This code is mine most of the part. Guide me if I missed something wrong. Feel free to comment thanks.

How to assign a Value taken from the database to a label?

I need to assign a string taken by a query from the database to a Jlabel. I tried many methods but failed. How can i do it?
try{
String sql="SELECT MAX(allocationID) FROM allocation where unit='"+ dept + " ' ";
pst=conn.prepareStatement(sql);
String x= (pst.execute());
}
catch(Exception e){
}
Need to study the steps to connect to the database in java First db steps
Get the resultset from the statment by calling ResultSet rs = pst.execute();
Iterate through the list of rows by using the resultset object.
After that assign the value to the JLabel.
You just made several errors in your tiny program, take a look at the code below as an example:
// your way of using prepared statement is wrong.
// use like this
String sql="SELECT MAX(allocationID) FROM allocation where unit=?;";
Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
// assign values to the variables in the query string
ps.setString(1, dept);
// execute the query
ResultSet rst = ps.executeQuery();
// parse the result set to get the value
// You'd better do some check here to ensure you get the right result
rst.next();
String x = rst.getInt(1) + "";
ps.close();
conn.close();
}
Have a look at the article if you are interested:https://docs.oracle.com/javase/tutorial/jdbc/basics/retrieving.html

Updating database after updating resultset

I have the below code to get data from a database and update it. How ever, result set is getting updated but, I don't see the changes in the database. Even after I say commit(), database is not getting updated. What am I missing here?
Connection connect = ConnectionManager.getInstance().getConnection();
Statement st = connect.createStatement();
st.execute("Select * from ...");
ResultSet rs = st.getResultSet();
ResultSetMetaData md = rs.getMetaData() ;
rs.absolute(1);
rs.updateObject("StepName","ABCD" );
connect.commit();
//connect.close();
EDIT:
Now, i have the below method, but I get the error as indicated.
rs.updateString("StepName", "ABCD");
rs.updateRow();
//rs.updateObject("StepName","ABCD" );
Error: com.jnetdirect.jsql.u: sp_cursor: The cursor identifier value provided (0) is not valid.
OK I have it working now. Below is the way I had to change.
Working solution:
Connection connect = ConnectionManager.getInstance().getConnection();
Statement st = connect.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
st.execute("Select * from ...");
ResultSet rs = st.getResultSet();
String queuename = "apples";
String updatedname = "bananas";
while(rs.next())
{
if(rs.getString(3).equals(queuename))
{
rs.updateString(3, updatedname );
System.out.println("updated: " + rs.getString(3));
rs.updateRow();
}else
{
System.out.println(rs.getRow() + ": " + rs.getString(3));
}
}
connect.commit();
rs.close();
connect.close();
}
If you look at the spec of updateObject :
Updates the designated column with an Object value. The updater methods are used to update column values in the current row or the insert row. The updater methods do not update the underlying database; instead the updateRow or insertRow methods are called to update the database.
rs.updateObject alone doesn't update the database. Try adding a call to rs.updateRow() after updateObject.
rs.absolute(1); might be not be moving the cursor. Try:
rs.next();
You can try a straight up SQL statement:
StringBuffer updates = new StringBuffer();
updates.append("UPDATE table_name ");
updates.append("SET StepName = ? );
updates.append("WHERE id = ?");
Statement updateStatement = connect.createStatement(updates.toString());
updateStatement.setString(1, "BlaBla");
updateStatement.setInt(2, 143);
updateStatement.executeUpdate();
When you make your call to createStatement you need to use the overload that allows you to specify an updatable resultset.
Here is an example if found: http://www.xyzws.com/Javafaq/how-to-use-updatable-resultset-in-jdbc/179
I think it's possible that not all driver\databases support this operation.

Categories

Resources