Data in the ResultSet ceases to exist when a getString is executed - java

I am working on a small practice game that takes the names of the winner and loser and increments their records in a database. I'm using an access database. i have been able to successfully get data inserted into the database but have failed to build upon the name already there. the resultset shows the data that is needed but when i go to pull the data with a getString, the data disappears. here is a piece of the code.
public int getWins() {
try {
String StrWin = ult.getPlayerWin();
rset = stmt.executeQuery("SELECT Name, Wins FROM t_Records;");
while (rset.next()) {
String DataWin = rset.getString("Name");
if (StrWin == DataWin) {
wins = rset.getInt("Wins");
rset.close();
return wins;
}
}
rset.close();
return -1;
} catch (Exception e) {
e.printStackTrace();
return -1;
}
This code throws a no data found exception. Why does the data cease to exist when the getString has been executed?

Related

check row if not exist mysql and got output to boolean bukkit

I have tried this so many times but I never did it, this is my code
public static Boolean checkhaveguild(String name) {
try {
Statement statement = connection.createStatement();
PreparedStatement ps = connection.prepareStatement("SELECT * FROM guild");
System.out.println(statement.execute("SELECT * FROM guild WHERE name = "+name+""));
System.out.println("----------");
} catch (SQLException e) {
throw new RuntimeException(e);
}
return false;
}
I am doing a guild plugin on BungeeCord and getting data from MySQL
The code is about checking if the row does not exist and output to boolean
I'd suggest you to learn more about the basics of programming in Java! Minecraft is a great way to start into programming, but you should be interested in doing things properly.
public static boolean hasGuild(String name) {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connection.prepareStatement("SELECT COUNT(name) FROM guild WHERE name = ?");
statement.setString(1, name);
resultSet = statement.executeQuery();
if (resultSet.next()) return resultSet.getInt(1) > 0;
} catch (SQLException e) {
// TODO properly handle exception
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// TODO properly handle exception
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// TODO properly handle exception
}
}
}
return false;
}
Some thoughts on what this code is doing:
Asking the database for the number of rows whose name column matches the given string. Always make sure that you only request the data that's necessary for your purpose. Requesting all columns with their data is overkill if you only want to answer if there are any rows or not.
If the number of rows is greater than zero, it'll return true, because there are rows with a matching name column.
Some thoughts you should make yourself:
What is contained in the name column? If it's the guild's name, then that's fine, but if that's the player's name you should consider re-thinking your code. Player's in Minecraft can change their name and hence would lose their guild on your server. Players in Minecraft are uniquely identified by their UUID, which will never change. Maybe consider using the UUID then!
In order for the query to be as fast a possible you should set an INDEX on the name column. That will speed up the lookup proccess even if there are plenty of rows!
Nevertheless: Welcome to StackOverflow! I hope that I could help you and I wish lot's of fun with programming.
in the try, i try sout resultSet and statement before close and it send this to me
resultSet :
com.mysql.cj.jdbc.ClientPreparedStatement: SELECT COUNT(name) FROM guild WHERE name = 'a'
statement :
com.mysql.cj.jdbc.ClientPreparedStatement: SELECT COUNT(name) FROM guild WHERE name = ** NOT SPECIFIED **
and return false is my test at last it will return true if it have if not it will return false

How to make SQL delete method validate the data properly

I got a method that deletes a record in the database when inserting a tag value. when a record is deleted, a message in the console screen pops up saying "this record has been deleted ". It works fine when inserting a valid tag value. However, when I insert an invalid tag value that doesn't exist in my database it acts like it has deleted it and displays that previous message. Although within my method says if the outcome is not equal 1 (which is not true) return false, but it's apparently not validating the inserted data. Can anyone tell me what's the problem
public boolean DeleteWallet(String Tag) throws SQLException {
System.out.println("Deleting wallet");
Connection dbConnection = null;
Statement statement = null;
int result = 0;
String query = "DELETE FROM wallets WHERE Tag = '" + Tag + "';";
try {
dbConnection = getDBConnection();
statement = dbConnection.createStatement();
System.out.println("The record has been deleted successfully");
// execute SQL query
result = statement.executeUpdate(query);
} finally {
if (statement != null) {
statement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
if (result == 1) {
return true;
} else {
return false;
}
}
The statement
System.out.println("The record has been deleted successfully");
is being printed before you actually perform any database operations statement.executeUpdate(query);
Instead, you should perform your database operation within your try statement, then print your success output. If the statement fails (IE an exception is thrown) the success statement will be skipped.
Additionally, instead of relying on the output the the executeUpdate(query) to determine if your query was successful, I would always assume your query or some operation before the query fails, and only return true if all database processing was successful.
Finally, the use of prepared statements will help make your query easier to read, use, and is better secured against SQLInjection attacks.
Example:
public class DatabaseOperations {
public boolean DeleteWallet(String Tag) {
//Query used for prepared statement
static final String DELETE_QUERY = "DELETE FROM wallets WHERE Tag=?";
System.out.println("Attempting to delete wallet using query:" + DELETE_QUERY);
//assume DELETE operation fails due to exection at any stage
Boolean result = false;
try (
//Objects that can automatically be closed at the end of the TRY block
//This is known as AutoCloseable
Connection dbConnection = getDBConnection();
PreparedStatement statment = dbConnection.preparedStatement(DELETE_QUERY))
{
//replace ? with Tag
statement.setString(1, Tag);
int row = preparedStatement.executeUpdate();
//If statement fails skip to catch block
result = true;
System.out.println("The record in row " + row + " has been deleted successfully");
} catch (SQLException sqle) {
//likely thrown due to "Record Not Found"
//TODO investigate further for the specific exception thrown from the database implementation you are using.
//TODO print helpful message to help user of this method resolve this issue
} catch (Exception) {
//TODO handle any other exceptions that may happen
}
return result;
}
}

jsp control server side on form

I want compare to the data sent with all data in the db. this coce compare the date insert only with the last row. how can I compare with all row in the db?
................................................................................................
String sData= request.getParameter("idatadata");
String sAzienda= request.getParameter("idazienda");
String sCommessa= request.getParameter("idcommessa");
String date = "";
String company = "";
String order = "";
Connect con = new Connect();
try {
Connection connection = con.createConnection();
Statement statement = connection.createStatement();
String sql ="SELECT * FROM table";
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()) {
date = resultSet.getString("iddata");
company = resultSet.getString("idazienda");
order = resultSet.getString("idcommessa");
}
if((sData.equals(date) && sAzienda.equals(company)) && sCommessa.equals(order)) {
out.print("already sent");
con.closeConnection(connection);
}
else {
DbConnect.insertInDb(connection, sData, sOre, sMinuti, sAzienda, sCommessa, sRifInterno);
dbc.closeConnection(connection);
response.getWriter().append("ok! ");
}
} catch (Exception e) {
e.printStackTrace();
}
}
The reason why you are checking only the last row, is that your while loop keeps overwriting your local variables each time you retrieve a row:
while(resultSet.next()) {
// these lines overwrite the local vars for each row
date = resultSet.getString("iddata");
company = resultSet.getString("idazienda");
order = resultSet.getString("idcommessa");
}
But you don't actually check the local vars inside the loop before moving on to the next row from the db. You should add the check into the loop:
while(resultSet.next()) {
date = resultSet.getString("iddata");
company = resultSet.getString("idazienda");
order = resultSet.getString("idcommessa");
// add your check here
if((sData.equals(date) && sAzienda.equals(company)) && sCommessa.equals(order)) {
out.print("already sent");
break;
}
}
Preferably, just perform a select based on the data you are looking for. If you get no results, then the data isn't in the db. This method is much more efficient. If you do decide to go down this path (which is a good idea), use a prepared statement so that you don't introduce a SQL injection vulnerability into your code.

How to check if deletion was successful in the database?

I wanted an error to popup, when the user entered a wrong id into the delete field. But even if a wrong id is entered, the query still proceeds, but no data is deleted. Here's my code:
String value = jTextField19.getText();
if (value == null || "".equals(value)) {
JOptionPane.showMessageDialog(null, "The field is blank!");
} else {
theQuery("DELETE FROM inventorydb WHERE item_id=('"+jTextField19.getText()+"') AND item_id IS NOT NULL");
}
The theQuery method:
private void theQuery(String query) {
Connection con = null;
Statement st = null;
try {
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/inventory", "root", "");
st = con.createStatement();
st.executeUpdate(query);
JOptionPane.showMessageDialog(null, "Done!");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null,"Error!");
}
}
First of all: do not ever directly build SQL queries from user input, use prepared statements instead. If you don't know about SQL Injection, you should.
If you are using JDBC, you can check the result of #executeUpdate() to see how many rows were affected. If it was zero, then you can say that it was a wrong id.
This is the method definition:
public int executeUpdate(java.lang.String sql)
The return value is:
An int that indicates the number of rows affected, or 0 if using a DDL statement.
In the program at hand, you can just simply do this:
int deleted = st.executeUpdate(query);
if (deleted == 0) {
JOptionPane.showMessageDialog(null, "Nothing to delete!");
return;
}

Is it Ok to Pass ResultSet?

In my situation, I am querying a database for a specific return (in this case registration information based on a username).
//Build SQL String and Query Database.
if(formValid){
try {
SQL = "SELECT * FROM users WHERE username=? AND email=?";
Collections.addAll(fields, username, email);
results = services.DataService.getData(SQL, fields);
if (!results.next()){
errMessages.add("User account not found.");
} else {
user = new User();
user.fillUser(results); //Is it ok to pass ResultSet Around?
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
services.DataService.closeDataObjects(); //Does this close the ResultSet I passed to fillUser?
}
}
So once I query the database, if a result is found I create a new User object and populate it with the data I received from the database. I used to do all of this directly in the method that I was pulling the resultset into, but I realized I was doing a lot of redundant coding throughout my project so I moved it all into one central method that lives in the actual User bean.
public void fillUser(ResultSet data) throws SQLException{
setUserId(data.getInt("id"));
setFirstName(data.getString("first_name"));
setLastName(data.getString("last_name"));
setUsername(data.getString("username"));
setType(data.getString("type"));
setEmail(data.getString("email"));
}
I have done a few tests and from what I can determine, because I close the original resultset in the finally block of the query, the resultset that I pass into the fillUser method also gets closed. Or am I wrong and am I seriously leaking data? This is actually the second time I pass a resultset (so its two instances of one) because the block I use to query my database is
public static ResultSet getData(String SQL, ArrayList fields) throws SQLException {
try{
connection = Database.getConnection();
preparedStatement = connection.prepareStatement(SQL);
for(int i=0; i<fields.size(); i++){
Integer num = i + 1;
Object item = fields.get(i);
if(item instanceof String){
preparedStatement.setString(num, (String) item); //Array item is String.
} else if (item instanceof Integer){
preparedStatement.setInt(num, (Integer) item); //Array item is Integer.
}
}
resultSet = preparedStatement.executeQuery();
return resultSet;
}finally{
}
}
All of these code snippets live in separate classes and are reused multiple times throughout my project. Is it ok to pass a resultset around like this, or should I be attempting another method? My goal is to reduce the codes redundancy, but i'm not sure if i'm going about it in a legal manner.
Technically, it's OK to pass result sets, as long as you are not serializing and passing it to a different JVM, and your JDBC connection and statement are still open.
However, it's probably a better software engineer and programming practice to have DB access layer that returns you the result set in a Java encoded way (a list of User in your example). That way, your code would be cleaner and you won't have to worry if the ResultSet is already opened, or you have to scroll it to the top, you name it...
As everyone before me said its a bad idea to pass the result set. If you are using Connection pool library like c3p0 then you can safely user CachedRowSet and its implementation CachedRowSetImpl. Using this you can close the connection. It will only use connection when required. Here is snippet from the java doc:
A CachedRowSet object is a disconnected rowset, which means that it makes use of a connection to its data source only briefly. It connects to its data source while it is reading data to populate itself with rows and again while it is propagating changes back to its underlying data source. The rest of the time, a CachedRowSet object is disconnected, including while its data is being modified. Being disconnected makes a RowSet object much leaner and therefore much easier to pass to another component. For example, a disconnected RowSet object can be serialized and passed over the wire to a thin client such as a personal digital assistant (PDA).
Here is the code snippet for querying and returning ResultSet:
public ResultSet getContent(String queryStr) {
Connection conn = null;
Statement stmt = null;
ResultSet resultSet = null;
CachedRowSetImpl crs = null;
try {
Connection conn = dataSource.getConnection();
stmt = conn.createStatement();
resultSet = stmt.executeQuery(queryStr);
crs = new CachedRowSetImpl();
crs.populate(resultSet);
} catch (SQLException e) {
throw new IllegalStateException("Unable to execute query: " + queryStr, e);
}finally {
try {
if (resultSet != null) {
resultSet.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
LOGGER.error("Ignored", e);
}
}
return crs;
}
Here is the snippet for creating data source using c3p0:
ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass("<driver class>"); //loads the jdbc driver
} catch (PropertyVetoException e) {
e.printStackTrace();
return;
}
cpds.setJdbcUrl("jdbc:<url>");
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
javax.sql.DataSource dataSource = cpds;

Categories