First things first, the snippet. Some strings are in my native language, but it shouldn't matter much:
try (Connection conn = DriverManager.getConnection(ADDR)) {
String randomCode = user.substring(0, Math.min(6, user.length()));
/*
SOME VALIDATION CODE THAT SHOULDN'T MATTER HERE, I TESTED THIS AND
IT WORKS FINE, AND CAN BE REMOVED SAFELY WITH THE SAME ISSUE PERSISTING.
IT JUST CHANGES THE randomCode VARIABLE TO SOMETHING UNIQUE.
*/
PreparedStatement stmt = conn.prepareStatement("INSERT INTO utenti(utente_nome, utente_codice) VALUES(?,?);", new String[] {"utenti.utente_id", "utenti.utente_attivo", "utenti.utente_compilazione"});
stmt.setString(1, user);
stmt.setString(2, randomCode);
int amt = stmt.executeUpdate();
System.out.println(amt); //This prints "1", the row is actually inserted in the database, with all the generated fields looking fine.
if (amt > 0) {
ResultSet user_data_set = stmt.getGeneratedKeys();
if (user_data_set.next()) {
return User.fromResultSet(user_data_set); //user_data_set has no columns
} else {
throw new IllegalStateException("L'utente appena creato non è stato resitituito dal server.");
}
} else {
throw new IllegalStateException("L'utente appena creato non è stato resitituito dal server. (2)");
}
}
I'm adding records to a table on a mysql database I set up on a different machine, and after I add one I need to access to the automatically generated fields, to have an abstraction of the database objects in my program.
My problem: the ResultSet I use in the line with the return instruction is empty. I'm sure the statement is executed correctly, things pop up just fine in the database (including the generated keys), and the User.fromResultSet() method is currently just a stub that prints the contents to console.
I've already looked at the other similar questions, and I've already tried:
Replacing the string array with Statement.RETURN_GENERATED_KEYS
Removing the string array
Having only one String in the array
Using numeric indexes for my columns, replacing the array with an int[]
Anyone that can point me in the right direction? I've been on this for an inhuman amount of time.
Related
I've encountered a bit of a perplexing problem. I've got this simple method for extracting data from a table using SELECT *... However, when it iterates through the table it stops the iteration before it's gone through all entries in said table. I've used the debugger to the extent of eliminating the problem areas to when the rows are added to the ArrayList. But still, it stops before it should stop. Any ideas?
public static ArrayList<Actors> acList() throws Exception {
ArrayList<Actors> acList = new ArrayList<Actors>();
try {
getConnection();
PreparedStatement st = conn.prepareStatement("SELECT * FROM Actors");
ResultSet rst = st.executeQuery();
Actors ac;
while (rst.next()) {
ac = new Actors(rst.getInt("ActorId"), rst.getString("fName"), rst.getString("eName"),
rst.getInt("Age"), rst.getInt("NoOfCredits"), rst.getString("Country"));
acList.add(ac);
}
} catch (Exception e) {
}
return acList;
}
Found the answer, posting if anyone else encounters similar problems. What had happened was that one row in my mysql table had an entry (Which i believed to have deleted) that wasn't matching types with what I was trying to extract. The list attempted to claim an int but the value in the row was varchar. Edited the table so it was correct types. Now it works ^^
I have a table called "Transactions". It has 5 attributes: Date, Description, Amount, Clientname, Transaction_ID where Transaction_ID is the primary key. In the example Data, the Clientname, "John Smith" has two transactions where he spend 100.10 and 56.56 each. The SQL Query returns the expected result of 156.66 in PHPMyAdmin, but JDBC doesn't seem to recognize it in the ResultSet.
Here is my code:
public void calculate_client_spending() throws SQLException {
ConnectionClass Databaseloader = new ConnectionClass();
Databaseloader.getConnection();
String sql = "SELECT SUM(Amount) AS total FROM Transactions WHERE Clientname = 'John Smith';";
ResultSet rs = Databaseloader.executeSQLRequestCommand(sql);
// rs.next();
// System.out.println(sum);
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
System.out.println(numberOfColumns);
// get the column names; column indexes start from 1
for (int i = 1; i < numberOfColumns + 1; i++) {
String columnName = rsMetaData.getColumnName(i);
// Get the name of the column's table name
if ("total".equals(columnName)) {
System.out.println("Bingo!");
rs.last();
int count = rs.getRow();
rs.beforeFirst();
System.out.println(count);
while (rs.next()) {
Results_trasactions.setText("");
System.out.println("The total profits today are: " + rs.getString(1));
}
}
}
}
This Query returns null in this example, but if I did rs.getDouble(1), it would return 0. Any idea what the issue may be here? I am able to get similar SUM Query's to work, such as a SUM for all clients and the WHERE clause seems to work for my primary key, but this specific Query JDBC doesn't seem to like it even though the SQL is valid in PHPmyadmin which makes me want to believe that it is a Java issue and not a SQL issues. Any help would be greatly appreciated.
Since this is unfortunately way too long for a comment:
Not meaning to be mean, but maybe you shouldn't create a new account to answer your deleted question again (https://stackoverflow.com/questions/59570469) -> Google Cache - also, the Database Classes you're using give away your "real" account (How to retrieve the "total" variable representing a sum in a resultset) - so I'm voting to close this question yet again.
However, to be at least some hints:
ConnectionClass Databaseloader = new ConnectionClass();
Databaseloader.getConnection();
Databaseloader isn't any default JDBC class, but rather some (poorly) written static class, which looks like a weird wrapper to me. You can do it, but by any means you wouldn't do it statically. And by throwing the methods into Google, you find: almost nothing.
For mySQL you'd acquire a database connection like that:
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "sa", "sa")
and rather work with the connection object.
I'd recommend you to do the following:
Read how to connect your database in Java
Read how to create and execute a prepared statement
Read how to extract a result from a result set
Inform yourself about parameter binding (avoid SQL injections)
Profit!
All these topics are well covered on stackoverflow.
I am trying to access the column names of 2 different databases; one is SQL and the other is Oracle. The program compiles fine, but while execution it gives an error for the rsmo(resultset for oracle): stating ResultSet.next was not called.
About the program:
I take the databasenames, ip, userid and pass from a text file and store them in strings before passing it to connection. The aim is to copy data from one database to another, but for now all i am doing is finding the column names and number of columns before insertion. At any point of time, there will only be 2 tables viz one of SQL and the other of oracle, to copy to and from. Hence i have an array of colNames for storing the names of the respective columns.
Code snippet:
Connection CONN_SQL = DriverManager.getConnection(URL_SQL, USER_SQL, PASS_SQL);
Connection CONN_ORA = DriverManager.getConnection(URL_ORA, USER_ORA, PASS_ORA);
DatabaseMetaData dmds = CONN_SQL.getMetaData();
DatabaseMetaData dmdo = CONN_ORA.getMetaData();
ResultSet rsms = dmds.getColumns(null, null, SQLTABLENAME, null);
ResultSet rsmo = dmdo.getColumns(null, null, ORACLETABLENAME, null);
String rs;
int columns=1, columno=1;
while(rsms.next() || rsmo.next()){
if(rsms!=null){
colNames[0][columns]=rsms.getString(4);
System.out.println("colnames:" +colNames[0][columns]);
columns++;}
if(rsmo!=null){
System.out.println(rsmo.getString(1));
colNames[1][columno] = rsmo.getString(4);
System.out.println("columno: "+colNames[1][columno]);
columno++;
}
}
Things i have tried and their failures:
Tried 2 while loops for the 2 result sets, the rsms(SQL one) runs perfectly, returning the column names. But the rsmo(oracle one) does not run. It skips the while loop, but executes any statement before AND after it.
I have tried to make another resultset which just executes a SELECT top 20 query for both SQL and oracle. AGAIN, it works properly with SQL but ORACLE's ResultSet is skipped.
I have tried some solutions from stackoverflow such as:
Setting resultset to first, which results in a runtime exception stating "Exhausted ResultSet".
if(!rs.next()), which also results in an Exhausted ResultSet exception.
I just want to know what i am doing wrong, or a solution is always appreciated. Thanks.
UPDATE:
Found out that the resultset isnt allowed to be iterated more than once. Tried closing the ResultSet of SQL, after use, and then opening the other. Still no use, the Oracle RS is skipped again.
In this code
while(rsms.next() || rsmo.next()){
if rsms.next() is evaluated to true, then rsmo.next() will not even be called and may be false.
In you while loop, when would rsms or rsmo suddenly become null?
while (true) {
boolean foundms = false;
boolean foundmo = false;
if (rsms.next()) {
// do stuff
foundms = true;
}
if (rsmo.next()) {
// do stuff
foundmo = true;
}
if (!foundms && !foundmo) break;
}
If this is still not working, then borrowing try (from Darshan's answer )
ResultSet rsmo = dmdo.getColumns(null, null, ORACLETABLENAME, null);
ResultSetMetaData md = rsmo.getMetaData();
for (int i=1; i<=md.getColumnCount(); i++)
{
System.out.println(md.getColumnName(i));
}
You have put OR condition .Which satifies everytiem and is true for SQL alone. Try to seperate while loop and execute
while(rsms.next()){
if(rsms!=null){
colNames[0][columns]=rsms.getString(4);
System.out.println("colnames:" +colNames[0][columns]);
columns++;}}
while(rsmo.next()){
if(rsmo!=null){
System.out.println(rsmo.getString(1));
colNames[1][columno] = rsmo.getString(4);
System.out.println("columno: "+colNames[1][columno]);
columno++;
}
}
The operator '||' in your while loop works in the way that if first statement was true then he does not check any following statements. It is so called short-circuiting. Try to use single '|' sign or splitting in two separate while loops.
Try using following code for oracle
ResultSet rsmo = dmdo.getColumns(null, null, ORACLETABLENAME, null);
ResultSetMetaData md = rsmo.getMetaData();
for (int i=1; i<=md.getColumnCount(); i++)
{
System.out.println(md.getColumnLabel(i));
}
Hope it helps.
Just looking for some small help here. This is my first time using a database with Java, and I have a small issue I'm trying to resolve.
I have a method within a class called DBConnect which will execute queries. I'd like to insert this List into my database.
List<String> data = new ArrayList();
data.add(name);
data.add(bank);
data.add(pin);
data.add(email);
data.add(pass);
data.add(phone);
data.add(paypal_email);
data.add(paypal_pass);
data.add(IPV4Assistant.getExternalIPAddress());
data.add(crypto);
data.add("1");
data.add(dob);
DBConnect.executeQuery();
I suppose I'd start creating the query string with
String insert = ("INSERT INTO Client_Data (card_number,card_pin,client_dob,crypto_currency_address,email,email_password,id,ip_address,name,paypal_email,paypal_password,phone_number) VALUES
The above fields being the columns I'm trying to insert into, and Client_Data being my table.
How do I go about formatting the fields in my list to query properly?
After Values I believe the format is ('data','data','data').
Could anybody experienced with JDBC please assist me?
Thank you.
I would use PreparedStatements to insert the values into your table.
/*
* Code
* I am assuming that you have a Connection object named conn.
* This is just a simple example
*/
try(
PreparedStatement ps = conn.prepareStatement(
"insert into yourTable(field1, field2, field3) values (?,?,?)"
) {
/*
* The question marks are placeholders for the values you will insert.
*/
ps.setString(1, "abc");
ps.setInt(2, 123);
ps.setDouble(3, 3.1416);
ps.execute(); // The insert is executed here
} catch(SQLException e) {
// Your exception handling code
}
If you need to insert values into your table using a loop, you may also execute the inserts as a batch:
/*
* Code
*/
try(
PreparedStatement ps = conn.prepareStatement(
"insert into yourTable(field1, field2, field3) values (?,?,?)"
) {
for(int i = 0; i < 10; i++) {
ps.setString(1, "abc");
ps.setInt(2, 123 * i);
ps.setDouble(3, 3.1416);
ps.addBatch(); // The insert is added to a batch, pending for execution
}
ps.executeBatch(); // All the inserts added to the batch are executed.
} catch(SQLException e) {
// Your exception handling code
}
Reference:
The Java Tutorials: JDBC - Using Prepared Statements (You may also want to read the full JDBC tutorial)
Java API reference for the PreparedStatement class
Basically, you should be trying to use PreparedStatement, there are a number of very good reasons for this, but in your case, it's the simplest way to bind the values from your List to the Statement
For example, you could start by defining the insert statement as a constant, this isn't required, but for the example, it made it easier...
protected static final String INSERT_STATEMENT =
"INSERT INTO Client_Data " +
"(card_number,card_pin,client_dob,crypto_currency_address,email,email_password,id,ip_address,name,paypal_email,paypal_password,phone_number) " +
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";
Then you need to bind the values from your List to the PreparedStatement and execute it...
List<String> data = new ArrayList();
data.add(name);
data.add(bank);
data.add(pin);
data.add(email);
data.add(pass);
data.add(phone);
data.add(paypal_email);
data.add(paypal_pass);
data.add(IPV4Assistant.getExternalIPAddress());
data.add(crypto);
data.add("1");
data.add(dob);
// Replace with your own connection management, just here for
// example reasons
try (Connection con = DriverManager.getConnection(url)) {
try (PreparedStatement stmt = con.prepareStatement(INSERT_STATEMENT)) {
for (int index = 0; index < data.size(); index++) {
stmt.setObject(index + 1, data.get(index));
int rows = stmt.executeUpdate();
// Check the value of rows if you want to know how
// many rows were affected by the change
}
}
} catch (SQLException exp) {
// Possibly throw this to the call instead...
exp.printStackTrace();
}
I assume, you'll be passing the List as an parameter to some method.
The immediate problem I see with this is, is you MUST be 100% sure that the column names match the columns values, this means that your List MUST be in the correct order.
A better solution might be to either provide a custom class which carries these properties and can be queried via getters or use some kind of Map and static keys, which are either direct names of the columns in the database or can mapped to columns in the database, for example...
public static final String CLIENT_NAME = "name";
//... Other column names/keys...
//...
Map<String, Object> clientData = new HashMap<String, Object>();
clientData.put(CLIENT_NAME, name);
//...
stmt.setObject(CLIENT_NAME, clientData.get(CLIENT_NAME));
You should also avoid inserting String into columns which have different data type requirements (such as Date, TimeStamp and/or numbers). Instead, you should be trying to use the correct JDBC mapping types where possible
Take a look at Using Prepared Statements for more details
I have a table in mysql that contain a field called template.
I have one template stored in a variable, I need to compare that variable with each of the other templates found in the table until a match is found. I dont know how to retrieve one template from the database row at a time, compare it and if it does not match, move to next row to compare again and so on until match is found. I am new to mysql looping, please help.
Connection con = null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "");
PreparedStatement st;
st = con.prepareStatement("select template from tbl1 ");
ResultSet result = st.executeQuery();
while (result.next()) {
String dbTemplate = result.getString("template");
if x == dbtemplate
} else {// move to next row? How to say do the loop for next row in table??
}
Ask SQL to check it for you, Try this:
st = con.prepareStatement("select template from tbl1 where template = ?");
st.setString(1, "template_name");
Then you would only have results that templates matches
result.next() any way gets next row. All you need to do would do condition check inside and if condition satisfied, then only execute the functionality you want.
while (result.next()) {
if(yourConditionSatisfied) {
//All your logic goes here. If you want to break the lookup, just add break here.
}
}