public ResultSet runQuery(String cmd, String table, String[] keys, String[] values, String[] whereKeys, String[] whereValues, int limitStart, int limitCount) throws Exception
{
PreparedStatement stmt;
if(!(cmd.equals("INSERT") || cmd.equals("SELECT") || cmd.equals("UPDATE") || cmd.equals("DELETE")))
{
throw new Exception("CMD UNSUPPORTED! CMD must be INSERT, SELECT, UPDATE, or DELETE.");
}
String sql = "";
if(cmd.equals("INSERT"))
{
//Build Insert statement
sql += "INSERT INTO "+table+" (";
for(int i = 0; i < keys.length; i++)
{
sql += ""+keys[i]+"";
if(i!=keys.length-1)
sql+=",";
}
sql += ") VALUES(";
for(int i = 0; i < values.length; i++)
{
sql += "'?'"; //This line seems to be causing trouble for me...
if(i!=values.length-1)
sql+=",";
}
sql += ")";
}
Context: I am working on a class project, and was assigned the database team. I have very little experience with MySQL and was partnered up with someone that claims to have a ton of experience with MySQL and Java. This is the function he created for Insert, Select, Update and Delete. Every function I have created that uses one of these functions has had errors, and requires modification of this original runQuery function. The main thing I have been trying to work with is the "insert" command. I have to be able to create a User, Admin, or a Class (like a college class), and insert the appropriate information(names, userNames, passwords, tableID). I can create a user or admin without generating an error, but when I create a class, I get an error: http://imgur.com/g99Ru6h
public boolean createUser(String first, String last, String user, String pass)
{
String[] keys = {"FName", "LName", "UName", "Password"};
String[] vals = {first, last, user, pass};
try
{
runQuery("INSERT", "Users", keys, vals, null, null, 0, 30);
}catch(Exception e)
{
e.printStackTrace();
System.out.println(e);
return false;
}
return true;
}
public boolean createClass(int classID, String name, int adminID, String institution, String meetTimes)
{
String[] keys = {"ClassID", "ClassName", "AdminID", "Institution", "MeetTimes"};
String[] vals = {Integer.toString(classID), name, Integer.toString(adminID), institution, meetTimes};
try
{
runQuery("INSERT", "Classes", keys, vals, null, null, 0, 30);
}catch(Exception e)
{
e.printStackTrace();
System.out.println(e);
return false;
}
return true;
}
TL;DR: I am having trouble inserting new 'classes' into a table, and think the error relates back to the runQuery function. I have omitted the rest of the runQuery function for now, as I don't think its necessary for this problem, but I can add it in its entirety of 241 lines. Based on what I am seeing online in regards to this situation, preparedStatements seem like a much easier way to input info, no?
Thanks for reading through this and your possible help!
From the linked image to the stack trace it seems someone tries to execute a statement with arguments with ? place holders. The SQL engine complains that the argument for ClassID is '?'. It should be ? not '?' since numerical values do not need ''. Strange however is the fact that I can't spot any ClassID argument in the query.
Related
Hi my aim is to load combobox with vaules from a database the code below works fine with one issue i get two of the first item so what must i do to prevent this
public void loadCombos() {
try {
try {
String cs = "jdbc:mysql://localhost:3307/booksalvation6";
String user = "root";
String password = "letmein";
jComboBox2.removeAllItems();// make sure old data gone
PreparedStatement pstpost;
ResultSet rspost;
conCombos = DriverManager.getConnection(cs, user, password);
for (int i = 1; i < 11; i++) {
String querypost = "select * from post "
+ "WHERE postage_id =" + i;
// load postage selections
pstpost = conCombos.prepareStatement(querypost);
rspost = pstpost.executeQuery();
while (rspost.next()) {
String Mypost = rspost.getString(6);
jComboBox2.addItem(Mypost);
}
}
} catch (SQLException ex) {
Logger.getLogger(BasicFrame.class.getName()).log(Level.SEVERE, null, ex);
}
conCombos.close();
} catch (SQLException ex) {
Logger.getLogger(BasicFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
You are using PreparedStatement but not in proper way.
Since you are looking only for one column to fetch all the column values which have postage_id between 1 to 10.
You can achieve it in single query:
select unique(combo_value_column_name) from post
where postage_id>=? and postage_id<=?
set the parameter via calling PreparedStatement#setInt(index,value) set it 1 and 10.
Just fetch single column and only unique values.
It's better explained under Java Tutorial on Using Prepared Statements
Instead of calling JComboBox#addItem() first prepare the whole list then finally set it once.
Read more...
Final Note: Follow Java Naming Convention.
I am trying to make a simple PL/SQL-to-Java setup, where I make a function in PL/SQL and call it from Java, expecting a return value.
I am fairly new to PL/SQL and calling it in Java so my approach is probably just lacking understanding in how return values from SQL actually works.
My SQL Function looks like this:
CREATE OR REPLACE FUNCTION GET_BOOKED_COUNT(P_NO VARCHAR2)
RETURN NUMBER AS
RESULTS NUMBER := 0;
BEGIN
SELECT COUNT(*) INTO RESULTS FROM SEAT WHERE PLANE_NO=P_NO AND BOOKED IS NULL;
RETURN RESULTS;
END GET_BOOKED_COUNT;
Return a number pretty much. It needs to check a table of seats to see how many of them are not booked yet.
After trying to follow various other Stackoverflow posts, I tried to duplicate what they did but it keeps telling me that the Index Column is Invalid.
public static boolean isAllBooked(String plane_no) {
String sql = "{? = CALL GET_BOOKED_COUNT('?')}";
boolean res = false;
try {
Connection conn = getConnection("db_010", "db2014");
CallableStatement cs = conn.prepareCall(sql);
cs.setString(2, plane_no);
cs.registerOutParameter(1, Types.NUMERIC);
cs.executeUpdate();
int i = cs.getInt(1);
if(i == 0) {
res = true;
}
conn.close();
} catch (SQLException ex) {
Logger.getLogger(HelperClass.class.getName()).log(Level.SEVERE, null, ex);
}
return res;
}
It's probably an easy fix, so what am I doing wrong exactly?
Your second bind variable, the argument to the function, should not be enclosed in single quotes. You're passing the literal value '?', not defining a bind:
String sql = "{? = CALL GET_BOOKED_COUNT(?)}";
The way you then refer to both parameters seems to be OK.
I am currently working on a Java project (on NetBeans) and I am struggling with a problem.
In fact, I have a jTable which contains several elements, which element has a jCheckBox in the second column and I would like to make a query to add the selected element (selected by the jCheckBox of course) in a table.
I can get the data that I want to add, but my query works only once. I have already check my loop but I don't where the problem comes from.
I let you see the code :
try {
// Getting id of the selected value in the jComboBox
String idParcours = oParcoursDAO.findIdParcours(jComboBoxParcours.getSelectedItem().toString());
int id = Integer.parseInt(idParcours);
// for each value in the jTable
for(int i=0; i <jTable2.getRowCount(); i++){
boolean isChecked = (Boolean)jTable2.getValueAt(i, 1);
String nomPoi = (String)jTable2.getValueAt(i, 0);
// if the value is selected
if(isChecked){
String IDPoi = oParcoursDAO.findIdPoi(nomPoi);
int idpoi = Integer.parseInt(IDPoi);
System.out.println("idpoi "+idpoi); // It works I saw as idpoi as I have choose
System.out.println("id "+id) // It works too
oParcoursDAO.addPoi(idpoi,id); // it works only once
}
}
}catch (SQLException ex) {
Logger.getLogger(ModificationParcoursJInternalFrame.class.getName()).log(Level.SEVERE, null, ex);
}
Thank you in advance for your help.
This is my statement
public void addPoi(int idPoi,int idParcours) throws SQLException{
String query = "INSERT INTO TB_POI_PARCOURS (id_poi,id_parcours) VALUES (?,?) ";
PreparedStatement preparedStatement = conn.prepareStatement(query);
preparedStatement.setInt(1,idPoi);
preparedStatement.setInt(2,idParcours);
preparedStatement.executeUpdate();
preparedStatement.close();
}
Why are you running one query per line? You can execute all of them in a single SQL using batch queries. It will require you to change the code but it will make it more efficient:
public void addPoi(Map<integer,Integer> poiMap) throws SQLException{
String query = "INSERT INTO TB_POI_PARCOURS (id_poi,id_parcours) VALUES (?,?) ";
PreparedStatement preparedStatement = conn.prepareStatement(query);
for(Integer idPoi:poiMap.keySet()) {
preparedStatement.setInt(1,idPoi);
preparedStatement.setInt(2,poiMap.get(idPoi));
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
preparedStatement.close();
}
Of course the original method has to be changed accordingly.
I am writing a java function to delete all data from MySQL table and then write new data in it. following is my function.
public void editsnack(ArrayList snames)
{
System.out.println("Snack Names "+snames);
Statement _snacksListStmt = null;
Statement _deleteTableDtataStmt = null;
try
{
_snacksListStmt = fCon.createStatement();
_deleteTableDtataStmt = fCon.createStatement();
int i=0;
for(i=0;i<snames.size();i++)
{
String _name = snames.get(i).toString();
String _deleteTableData ="TRUNCATE TABLE snacklist";
_deleteTableDtataStmt.executeUpdate(_deleteTableData);
String _snackListQuery ="insert into snacklist(snackName)values('"+_name+"')";
System.out.println("Query ");
System.out.println(_snackListQuery);
_snacksListStmt.executeUpdate(_snackListQuery);
}
}
Note that after deleting data successfully, these lines
System.out.println("Query ");
System.out.println(_snackListQuery);
are printing correct values, however values are not being stored in the table.
How can I solve this problem?
First of all, you're deleting all data for each item you are inserting.
So move the TRUNCATE code to before the for-loop
And see if you can sanitize the snack-names before adding them in the SQL, or they could cause sql-injections
Depending on if your connection is set on autoCommit or not you'd have to call fCon.commit() to commit your transaction.
Also you should always close your statements when you're done.
The problem is the delete query in the for loop, you are truncating the data after each insert. With your current logic only the last insert will reamin in the table and all other data will be truncated. Move the delete query outside of for loop and try:
String _deleteTableData ="TRUNCATE TABLE snacklist";
_deleteTableDtataStmt.executeUpdate(_deleteTableData);
for(i=0;i<snames.size();i++)
{
String _name = snames.get(i).toString();
String _snackListQuery ="insert into snacklist(snackName)values('"+_name+"')";
System.out.println("Query ");
System.out.println(_snackListQuery);
_snacksListStmt.executeUpdate(_snackListQuery);
}
Try code below..
public void editsnack(ArrayList snames)
{
System.out.println("Snack Names "+snames);
Statement _snacksListStmt = null;
Statement _deleteTableDtataStmt = null;
try
{
_snacksListStmt = fCon.createStatement();
_deleteTableDtataStmt = fCon.createStatement();
String _deleteTableData ="TRUNCATE TABLE snacklist";
_deleteTableDtataStmt.executeUpdate(_deleteTableData);
int i=0;
for(i=0;i<snames.size();i++)
{
String _name = snames.get(i).toString();
String _snackListQuery ="insert into snacklist (snackName) values ('"+_name+"')";
System.out.println("Query ");
System.out.println(_snackListQuery);
_snacksListStmt.executeUpdate(_snackListQuery);
}
}
My JAVA script consists of 2 JAVA classes: RMS, queryRMS
In the RMS class I call the method in the queryRMS class
RMS Java Class (I left out the start execution part, below is just the method)
for (int i = 1; i <= itemCount; i++) {
GlobalVariables.numberRow = i;
JavaDatapool.settings();
String item = queryRPM.connectDB_Multi(configFile,"SELECT ITEM FROM ORDSKU WHERE ORDER_NO = '" + orderNo + "' ORDER BY ITEM ASC",i);
JavaDatapool.writeXLS("item",item,GlobalVariables.sheetXLS);
sleep(1);
}
queryRMS JAVA class
public static String connectDB_Multi(String configFile, String query, int i) throws FileNotFoundException, IOException, SQLException, ClassNotFoundException{
Properties p = new Properties();
p.load(new FileInputStream(configFile));
String serverName = (p.getProperty("RMS_DBServerName"));
String portNumber = (p.getProperty("RMS_PortNumber"));
String sid = (p.getProperty("RMS_SID"));
String url = "jdbc:oracle:thin:#//" + serverName + ":" + portNumber + "/" + sid;
String username = (p.getProperty("RMS_Username"));
String password = (p.getProperty("RMS_Password"));
// jdbc:oracle:thin:#//localhost:1521/orcl
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connection = DriverManager.getConnection(url,username,password);
String setr = null;
try {
Statement stmt = connection.createStatement();
try {ResultSet rset = stmt.executeQuery(query);
try {
while(rset.absolute(i))
setr = rset.getString(1);
return setr;
}
finally {
try { rset.close();
}
catch (Exception ignore) {}
}
}
finally {
try { stmt.close();
}
catch (Exception ignore) {}
}
}
finally {
try { connection.close();
}
catch (Exception ignore) {}
}
}
So what it does is call the connectDB_multi class and then returns the String where the next part is saving it inside an Excel worksheet.
The loop should return all rows, one at a time and then save it inside the Excel worksheet.
In the second time in loop the query is faulted, eventhough the query should return 1 column consisting of 2 rows.
the original contained the part while(rset.next()) instead of while(rset.absolute(i))
but next only return the first row everytime. so the script works when only one column and row is retrieved from the Database.
Your logic looks a bit messed up.
Look at the first loop you posted. You are, effectivly, executing:
SELECT ITEM FROM ORDSKU WHERE ORDER_NO = '" + orderNo + "' ORDER BY ITEM ASC
itemCount number of times. Each time you execute it, you are attempting to access the n:th row, n being loop counter. Do you see a problem there? How do you know that the query will return itemCount number of rows? Because if it doesn't, it will fail since you are attempting to access a row that doesn't exist.
What I suspect you WANT to do is something like this
Statement stmt = connection.createStatement();
ResultSet rset = stmt.executeQuery(query);
while(rset.next()) {
JavaDatapool.writeXLS("item",rset.getString(1),GlobalVariables.sheetXLS);
}
You should also seriously consider using some form of connection pooling to avoid having to re-open new connections all the time as that is a pretty time-consuming operation.
This code seems very inefficient, for each row you want to fetch from the database you read a property file, create a connection, select all matching rows, skip ahead to the row you want and return just that row. (Or at least I think that is what you are trying to do).
Your code
while(rset.absolute(i))
setr = rset.getString(1);
is probably an infinite loop as it will continue to go to the same row as long as it is ok to go to that row, so either that row does not exist (and the while exists) or the row does exist (and while continues forever).
You should probably restructure your program to only do one select and read all rows that you want and store them in your excel file. While doing this, you can debug to see if you actually are getting the data you expect.
Apart from the inefficient code of creating new connections and querying once for each row, how do you know how many rows you want?
I think in the end you want something like this
....
while(rset.next()) {
JavaDatapool.writeXLS("item",item,GlobalVariables.sheetXLS);
}
And what is the sleep(1) support to accomplish?
FYI: if you open and close statement too often as your logic or pap's solution, you can get the " java.sql.SQLException: ORA-01000: maximum open cursors exceeded" error message.
I suggest you to not do 'too much generalize'. I saw a lot of OOP programmers overdid generalization and that is painful. You should design by a goal and the goal should not be 'just alignment' nor 'code look beautiful', it has to have a purpose for designing.