Inconsistent counting columns of insert in DAO - java

I'm developing a n-tier java app and when implement the insert method, I get this error:
(conn=146) Column count doesn't match value count at row 1
I´m using a mariadb database and a logic-DAO-View model
Here is the code:
DAO:
try {
Statement st = conex.getConnection().createStatement();
st.executeQuery("INSERT INTO abas001 (abas_cod, abas_cnt, abas_vol, abas_und) VALUES ('"
+ miAbasto.getAbas_cod() + "', '"
+ miAbasto.getAbas_cnt() + "', '"
+ miAbasto.getAbas_vol() + "', '"
+ miAbasto.getAbas_und() + "', '"
+ "')");
} catch (SQLException e) {
System.out.println(e.getMessage());
JOptionPane.showMessageDialog(null,
"No se Registró, verifique la consola para ver el error",
"Error", JOptionPane.ERROR_MESSAGE);
}
}
//
And the view code:
botonGuardar.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
pabascnt = Integer.parseInt(txtcant.getText());
pabasvol = Double.parseDouble(txtvol.getText());
AbastosDao abdao = new AbastosDao();
AbastosLog parabl = new AbastosLog();
parabl.setAbas_cod(pabascod);
parabl.setAbas_cnt(pabascnt);
parabl.setAbas_vol(pabasvol);
parabl.setAbas_und(pabasund);
abdao.registrarAbasto(parabl);
mostrarDatosConTableModel();
}
});
}
Where is the error?
I think that the error is sending parameters to the DAO but I don't know.

Here is how you might convert this to use a PreparedStatement, which will also take care of a number of potential problems including preventing SQL Injection, and data type mapping of the values being inserted. I'd suggest you review the documentation on using PreparedStatements. In the meantime, I've included a simple example of how you might use a Prepared Statement.
PreparedStatement ps = conex.getConnection().prepareStatement(
"INSERT INTO abas001 (abas_cod, abas_cnt, abas_vol, abas_und) VALUES (?,?,?,?)");
try {
ps.setObject(1, miAbasto.getAbas_cod());
ps.setObject(2, miAbasto.getAbas_cnt());
ps.setObject(3, miAbasto.getAbas_vol());
ps.setObject(4, miAbasto.getAbas_und());
int rowsInserted = ps.executeUpdate();
} . . .
finally {
ps.close();
}
It's important to be aware that PreparedStatements may be reused, and doing so could improve the performance of your application. Additionally, If your application tends to call this method repeatedly for each element of a large set of inputs, you might consider refactoring for batch execution. I'll leave all of this to you as well as adding the necessary and appropriate error handling.

Related

Error when updating MySQL database using UPDATE - SET - WHERE method in Eclipse

I am making a program using Eclipse that allows the user to update the volume of chemicals everytime they’re restocked/used, which requires them to enter the ID of the chemical and the amount they would like to add/subtract. A query is then performed to search for the chemical's ID in the database, and its volume is updated accordingly.
However, I’m having difficulties getting the volume to update. I tried adapting MySQL’s UPDATE statement from this website to SET volume = volume + amount added, WHERE chemical ID = ID entered by the user; however, there appears to be some syntax errors in my code, more specifically at the UPDATE - SET - WHERE line:
public void IDEnter() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:8889/StockControlSystem","root","root");
Statement stmt = con.createStatement();
String sql = "Select * from Chemicals where `Chemical ID` ='" + txtChemical_ID.getText()+"'";
ResultSet rs = stmt.executeQuery(sql);
if(rs.next()) {
stmt.executeUpdate("UPDATE Chemicals" + "SET `Volume` = rs.getInt(Volume) + Integer.parseInt(AmountAdded.getText()) WHERE `Chemical ID` in (txtChemical_ID.getText())");
}
else {
JOptionPane.showMessageDialog(null, "Invalid chemical ID");
txtChemical_ID.setText(null);
}
} catch(Exception exc) {
exc.printStackTrace();
}
}
Since I'm still new to MySQL, can someone help me correct this? Thank you so much for your help!
Your whole query is badly formatted. Change your code to this:
stmt.executeUpdate("UPDATE Chemicals SET Volume = " +
rs.getInt(Volume) + Integer.parseInt(AmountAdded.getText())
+ " WHERE Chemical_ID in (" + txtChemical_ID.getText() + ")");
You cannot use ' single quotes when defining Column names in queries. Single quotes are used for string values!
Still, this would not be the best way to do this. use PreparedStatement!
This way:
String updateString = "UPDATE Chemicals SET Volume = ? WHERE Chemical_ID in (?)"; // Creation of the prepared statement, the ? are used as placeholders for the values
PreparedStatement preparedStatement = con.prepareStatement(updateString);
preparedStatement.setInt(1, rs.getInt(Volume) + Integer.parseInt(AmountAdded.getText())); // Setting the first value
preparedStatement.setString(2, txtChemical_ID.getText()); // Setting the second. I am supposing that this txtChemical_ID textField has values seperated by commas, else this will not work!
preparedStatement.executeUpdate();
If you need to read more for PreparedStatement there are a lot of great resources out there. They also protect against SQL injections.
I think your problem might be with the "rs.getInt(Volume)"
Yours:
"UPDATE Chemicals" + "SET `Volume` = rs.getInt(Volume)
+ Integer.parseInt(AmountAdded.getText())
WHERE `Chemical ID` in (txtChemical_ID.getText())"
Can you try this:
"UPDATE Chemicals" + "SET `Volume` = " +
Integer.parseInt(AmountAdded.getText()) + "
WHERE `Chemical ID` in (" + (txtChemical_ID.getText()) +")"

How to update a row of entries in a database (JavaDatabase) that is connected to my JTable?

I am making a program without knowing much about programming... I used some youtube videos to help me.
My program is made for a chef that can edit users & food and gather ratings and suggestions from the inspector. The chef's section of editing users' details works.
However, the inspector's rating does not as it throws an error: SQLSyntaxException: Encountered "Vegetarian" at line 1, column 65. I believe it is because of getting the rating value (which is int) in a wrong way...
'
public void getConnection(){
try{
myconObj = DriverManager.getConnection("jdbc:derby://localhost:1327/MyApp", "Me", "Me");
mystatObj=myconObj.createStatement();
myresObj=mystatObj.executeQuery("Select * from Me.Food");
tableRateFood.setModel(DbUtils.resultSetToTableModel(myresObj));
}
catch (SQLException e){
e.printStackTrace();
}
}
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
try{
String sql = "update Me.Food set Name = '" + nameText.getText()
+ "',Type = '" + typeText.getText()
+ "', Rating = '" + ratingText.getText()
+ ", 'Vegetarian = '" + vegetarianText.getText()
+ "', ShownOnMenu = '" + showText.getText()
+ "' where Id = " + idText.getText();
//tried the following... did not work either
/*+ " Rating = " + Integer.parseInt(ratingText.getText()));*/
Statement update= myconObj.createStatement();
update.executeUpdate(sql);
JOptionPane.showMessageDialog(null, "Updated successfully!");
}
catch(SQLException E){
E.printStackTrace();
}
getConnection();
}
Your forgot a quote in ", 'Vegetarian = '"
Talking about building query strings, you should avoid +-ing values and rely on prepared statements with sql parameters instead. Allows the database to cache the query and avoids sql injection attacks. And spares you formatting headache, think about date values.

How to write a MySQL query in Java with user parameters with dates [duplicate]

This question already has answers here:
Passing parameters to a JDBC PreparedStatement
(5 answers)
Closed 9 years ago.
First of all guys thanks for the previous help and advice. I am only learning databases and MySQL, so please bear with me while I ask so major newbie type questions.
I'm entering 2 parameters, one is a string and the other is a date. I then want to then output of a another value. The string is straight forward but I'm unable to compare the dates properly. If the dates and the strings match then that is the record I'm looking for
Here is a copy of the table
private String agentDetail = "CREATE TABLE AgentDetail ("
+ "idNo INT(64) NOT NULL AUTO_INCREMENT,"
+ "initials VARCHAR(2),"
+ "agentDate DATE,"
+ "agentCount INT(64), "
+ "PRIMARY KEY(idNo))";
The problem is that it always brings back all the dates, both the correct and incorrect results
and here is the code that I am currently using
protected void getAgentIdNo (Connection con, PreparedStatement preStatement,
ResultSet result, String initials, Date myDate) {
try {
preStatement = con.prepareStatement("SELECT * FROM AGENTDETAIL");
result = preStatement.executeQuery();
while (result.next()) {
if (result.getString("initials").equals(initials)){
if (myDate.compareTo(result.getDate("agentDate")) == 0){
System.out.println("The date and initials matched !!");
System.out.println("The id no is " + result.getint("idNo");
}
}
}
}
catch (SQLException ex) {
System.out.println("An error occured when reading from the data base");
ex.printStackTrace();
}
}
I also know that this code is far from perfect so feel to suggest a more professional looking code.
Thanks in advance for any all help and support.
That was a bad idea. This is the way to do it:
preStatement = con.prepareStatement("SELECT * FROM AGENTDETAIL WHERE initials = ? AND angetDate = ?");
preStatment.setSring(1, initials);
preStatment.setDate(2, new java.sql.Date(date.getTime()));
Instead of make the filter programaticaly, i recommend (in this case to make a SQL query).
You can do something like:
protected void getAgentIdNo (Connection con, PreparedStatement preStatement,
ResultSet result, String initials, Date myDate) {
try {
preStatement = con.prepareStatement("SELECT * FROM AGENTDETAIL as ag WHERE ag.initial = ? AND date = ?");
preStatment.setSring(1,initials);
preStatment.setString(2,date);
result = preStatement.executeQuery();
while (result.next()) {
System.out.println("The date and initials matched !!");
System.out.println("The id no is " + result.getint("idNo");
}
}
}
catch (SQLException ex) {
System.out.println("An error occured when reading from the data base");
ex.printStackTrace();
}
}
Att: For more detail consult this link.
Hope it Helps ^^
First of all,
I would like to thank those who have read, reviewed and submitted a poor hacks work.
There was 2 different schools of thought that emerged and I of course tried both. It is great to try different methods.
I have found that for the code that I'm currently writing while I search for a job, this works very cleanly. However the other responses has also led me to investigate other opportunities that was given.
The segment is part of bigger system which I'm writing to increase my portfolio of work, What I am doing is using Java to create a visual interface, which will only assign one idNo to the user per day. The user may then come along and in another segment of code be given the opportunity to manually enter a customer number or alternatively generate one. This is where the idNo and agentCount numbers come in. By the way I found that command line code programming is way easier. :-)
protected void getAgentIdNo (Connection con, PreparedStatement preStatement, ResultSet result, AgentDetail ageDet) {
try {
preStatement = con.prepareStatement("SELECT * FROM AGENTDETAIL as ag WHERE ag.initials = ? AND ag.agentDate = ?");
preStatement.setString(1,ageDet.getInitials());
preStatement.setDate(2,ageDet.getMyDate());
result = preStatement.executeQuery();
while (result.next()) {
ageDet.setAgeIdNo(result.getInt("idNo"));
ageDet.setAgeCount(result.getInt("agentCount"));
}
}
catch (SQLException ex) {
System.out.println("An error occurred when reading from the data base");
ex.printStackTrace();
}
}
Thank you again Guys

Why rs.next() don't go to another record

If I remove beforeFirst() my function does only first record in ResultSet and go to end. If I use beforeFirst() I get an error ResultSet IS_TYPE_FORWARD_ONLY.
try {
ResultSet rs = stat.executeQuery("select _id, godziny_id from tblZmiany where harmonogram_id = " + h_id + " order by pracownik_id, Dzien");
rs.beforeFirst();
while (rs.next()) {
if (stat.executeUpdate("insert into tblWykonanie (Zmiana_id, Godziny_id) values ('" + rs.getLong(1) + "', " + rs.getInt(2) + ");") < 1) {
// Jeśli insert nie wstawił kolejnego rekordu
error_code = "Wystąpił problem podczas zatwierdzania harmonogramu.";
return false;
}
}
} catch (SQLException e) {
e.printStackTrace();
System.out.println(e.getMessage());
return false;
} catch (Exception e) {
error_code = e.getMessage();
return false;
}
return true;
You're using the same Statement object for both the SELECT and the INSERT. From the Javadoc:
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.
To fix the problem, use a separate Statement object for the executeUpdate() call.
Also, I strongly advise you to change the code to use PreparedStatement with bound arguments (represented by ?). Building SQL statements bit by bit as you're doing right now could open up security vulnerabilities.
Your code has a major security flaw. You are vulnerable to SQL injection. Never, ever, ever, ever, ever, ever, ever, use string concatenation with SQL statements; use PreparedStatements instead!
harmonogram_id = " + h_id + " order by pracownik_id,
Take a look here to see how your application could be easily owned with simple tricks:
http://en.wikipedia.org/wiki/SQL_injection
To answer your question though, it depends on your database. You have to set a property during the connection creation:
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE),
ResultSet.HOLD_CURSORS_OVER_COMMIT);
From:
http://docs.oracle.com/javase/1.4.2/docs/guide/jdbc/getstart/resultset.html#1012735

SQL queries through Java, "Illegal operation on empty result set"

I'm making a db call as follows:
String sqlAlert = "SELECT * FROM demotable where demo_no ='"
+rsDemo.getString("demo_no") + "'";
ResultSet rsAlert = db.GetSQL(sqlAlert);
if (rsAlert.next()) {
String newAlert = rsAlert.getString("cust3")+"1";
String newAlertSql = "UPDATE demotable SET cust3 = '" + newAlert + "' where demo_no='" + rsDemo.getString("demo_no") + "'";
System.out.println("Update alert msg: " + newAlertSql);
db.RunSQL(newAlertSql);
} else {
System.out.println("empty result. Demo_no = "+rsDemo.getString("demo_no"));
String sqlAlertinsert = "INSERT INTO demotable VALUES('" + rsDemo.getString("demo_no") + "','','','','','<unotes></unotes>')";
db.RunSQL(sqlAlertinsert);
System.out.println("insert demo done");
String sqlAlert2 = "SELECT * FROM demotable where demo_no ='"rsDemo.getString("demo_no") + "'";
ResultSet rsAlert2 = db.GetSQL(sqlAlert2);
if (rsAlert2.next()) {
String newAlert = rsAlert2.getString("cust3")+"1";
String newAlertSql = "UPDATE demotable SET cust3 = '" + newAlert+ "' where demo_no='" + rsDemo.getString("demo_no") + "'";
System.out.println("Update alert msg: " + newAlertSql);
db.RunSQL(newAlertSql);
}
rsAlert2.close();
}
rsAlert.close();
rs.close();
I am trying to insert rows into demographiccust if rsAlert returns an empty set and then access values from it. But my code returns this exception "Illegal operation on empty result set" around "if (rsAlert2.next()) { ". Why does it return an empty set even after inserting values into the table? Please help. Thank you.
It may be because of the open cursor. You must close your first Statement, prior trying the second. ResultSet is a connected thing, when you close the Statement it get closed too. I can't see the implementation of your db.RunSQL() and db.GetSQL() methods.
However, I am having the suggestion on how you should do it, in the first place. Here you go,
Update it without querying the database
Check how many rows updated. If none, then step 3, otherwise completed
Insert the record with the correct values in the first place. No need to update it after inserting.
Tips:
Try using PreparedStatement, instead
Try to stick with Java Naming Convention
Try using meaningful names, i.e. for example your method db.GetSQL() is not returning an SQL, but contrarily asking one, and in fact returning a ResultSet.
Never return a ResultSet. This may lead to bloated code and a lot of open cursors. Don't make the user of your method to close it. Close it yourself in your method where you are performing any database query, and return the result as a bean or a list of beans.
It's just a guess, but because you are interpolating rsDemo.getString("demo_no") directly into the SQL, you may be passing an SQL statement that isn't what you want. Try using the parameter binding api.

Categories

Resources