I have to add two queries to a table model so that it shows up on the table. It is a program doing prediction on soccer (EPL to be precise) and I need to display ALL results for the team when they are playing both home, and away. the first query is to get all the games where they play home, the second query is when they play away. Here is the code:
public void showResultsTotalTeam(){
deleteAllRows(dTableModel); // deleta all rows in the table
try {
conn = DriverManager.getConnection(connection.conn_url, connection.conn_user, connection.conn_pass);// connect to database server
Statement sqlState = conn.createStatement();// create statement for sql
String selectStuff = "SELECT games_team1, games_team2, games_winner, games_draw, games_team1_score, games_team2_score, games_month, games_day FROM games WHERE games_team1 = '" + cbxTeam1.getSelectedItem() + "'";// ststement for MySQL
rows = sqlState.executeQuery(selectStuff); // execute statement
String selectStuff2 = "SELECT games_team1, games_team2, games_winner, games_draw, games_team1_score, games_team2_score, games_month, games_day FROM games WHERE games_team2 = '" + cbxTeam1.getSelectedItem() + "'";// ststement for MySQL
rows2 = sqlState.executeQuery(selectStuff); // execute statement
Object[] tempRow;// create object array to store queried results
Object[] tempRow2;
while(rows.next()){ // while there are still values to be seen to
tempRow = new Object[]{rows.getString(1), rows.getString(2), rows.getString(3), rows.getString(4), rows.getString(5), rows.getString(6), rows.getString(7), rows.getString(8)};// add data to array
tempRow2 = new Object[]{rows2.getString(1), rows2.getString(2), rows2.getString(3), rows2.getString(4), rows2.getString(5), rows2.getString(6), rows2.getString(7), rows2.getString(8)};
dTableModel.addRow(tempRow); // add array to table model
dTableModel.addRow(tempRow2);
}
} catch (SQLException ex) {
// TODO Auto-generated catch block
System.out.println(ex.getMessage());
}
}
Now this code does not work and nothing shows up at all.
Please help? Any advice would be great.
You haven't loaded thr driver class
Class.forName("Driver Class Name");
And you haven't closed anything. Connecton & ResultSet
Unless the number of rows == number of rows2 then you may encounter trouble when you are iterating through rows.next
Also suggest you iterate do you code in two distinct blocks i.e one for rows and one for rows2
Edit
This could also be done with one query
SELECT games_team1, games_team2, games_winner, games_draw, games_team1_score,
games_team2_score, games_month, games_day FROM games
WHERE games_team1 = '" + cbxTeam1.getSelectedItem() + "' "
or games_team2 = '" + cbxTeam1.getSelectedItem() + "' "
Related
I have an sqlite database that i query from a java program, no insert, no table creation, just many many SELECT bundled with UNION (500 at a time).
How can I load the database from the .db into memory to speed up the SELECT?
Class.forName("org.sqlite.JDBC");
String urlJDBC = "jdbc:sqlite:";
String url = urlJDBC + dbPath;
Connection conn = null;
try {
conn = DriverManager.getConnection(url);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
for(int i=0, i<10000, i++)
{
String multipleSELECT = "SELECT a FROM table WHERE b=\"" + b1 + "\"" + "
UNION ... + " UNION SELECT a FROM table WHERE b=\"" + b500 + "\"";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(multipleSELECT);
check(rs);
}
Obviously the 500 values of b change at every iteration of i.
Is there a way to load the entire database in memory (about 2.5 GB, so less than the 8 GB ram)?
To speed up many small queries, wrap them in a single transaction, and use a single prepared statement with a parameter that changes. Then you should be able to use a simple SELECT that checks only one number.
Alternatively, write all numbers to check into a temporary table, and return all matching names at once:
SELECT a
FROM MyTable
JOIN TempTable ON MyTable.b = TempTable.b;
In either case, you can improve the lookup speed by using a covering index, i.e., a two-column index on the number and the name, or, better, by using a clustered index.
I am having some trouble in returning the NEXT record within the database, my code currently only returns the last record entered. I have tried creating an instance of a List/ArrayList, tried adding statements to my createStatement(); and just tried everything. I've searched the web, however, I always seem to get the last value returned. I was hoping as to whether someone could help me out. I am using .Swing and this is all executed within an ActionListener.
Essentially I want this function to get the next record in the database. As opposed to returning the last record.
nextEmployee.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Connection connection = null;
Statement statement = null;
try {
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite:employeeDatabase.sqlite");
connection.setAutoCommit(false);
System.out.println("Read operation - database successfully opened");
statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
ResultSet resultset = statement.executeQuery( "SELECT * from employees" );
while (resultset.next()) {
ArrayList<Employee> selectAllEmployees = new ArrayList<Employee>();
String id = resultset.getString("id");
String name = resultset.getString("name");
String email = resultset.getString("email");
String gender = resultset.getString("gender");
String dob = resultset.getString("dob");
String Address = resultset.getString("address");
String Postcode = resultset.getString("Postcode");
String NIN = resultset.getString("NIN");
String JobTitle = resultset.getString("JobTitle");
String StartDate = resultset.getString("StartDate");
String Salary = resultset.getString("Salary");
idTextField.setText(id);
nameTextField.setText(name);
genderTextField.setText(gender);
dobTextField.setText(dob);
addressTextField.setText(Address);
postcodeTextField.setText(Postcode);
ninTextField.setText(NIN);
jobtitleTextField.setText(JobTitle);
startdateTextField.setText(StartDate);
salaryTextField.setText(Salary);
emailTextField.setText(email);
}
resultset.close();
statement.close();
connection.close();
} catch ( Exception e1 ) {
System.err.println( e1.getClass().getName() + ": " + e1.getMessage() );
System.exit(0);
}
}});
Thank you for your time and effort.
One of two things is happening. Either:
You have a bug in the code which populates the database, so you think you have rows A, B, and C in the database, but in fact you only have row C
Or:
Your code as listed populates your controls with the contents of row A, then it repeats to populate the exact same controls with contents of row B, and then the exact same controls once more with the contents of row C. So, naturally, the values you are left with are the values of the last row.
It helps to think precisely what it is that you are trying to do, precisely what is happening, precisely what you expected to happen instead, and most importantly, what makes you believe that the code should do that which you expect it to do rather than what it actually does.
So I have a database that is made like this
{MATERIAL NAME;QUANTITY}
I also have a JTable in Java that uploads the info from the database (SQLite). As I edit a cell in the table, it automatically updates the database in this way:
//table listener
public void tableChanged(TableModelEvent e) {
//gets row and column if the table is edited
int row = e.getFirstRow();
int column = e.getColumn();
//change in sqlite
if (column == 1) {
int value = Integer.parseInt(table.getModel().getValueAt(row, column).toString());
String materialId = table.getModel().getValueAt(row, column-1).toString();
try (Connection c = DriverManager.getConnection("jdbc:sqlite:database.db"); Statement statement = c.createStatement()) {
String sql = "UPDATE MATERIALS set QUANTITY = " + value + " where MATERIAL='" + materialId +"';";
statement.executeUpdate(sql);
statement.close();
c.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
else if (column == 0) {
int value = Integer.parseInt(table.getModel().getValueAt(row, column+1).toString());
String materialId = table.getModel().getValueAt(row, column).toString();
try (Connection c = DriverManager.getConnection("jdbc:sqlite:database.db"); Statement statement = c.createStatement()) {
String sql = "UPDATE MATERIALS set MATERIAL = " + materialId + " where MATERIAL='" + materialId +"';";
statement.executeUpdate(sql);
statement.close();
c.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
It's okay when the quantity is updated. However, once the material name is updated, I don't know how I am supposed to update it in the database.
String sql = "UPDATE MATERIALS set MATERIAL = " + materialId + " where MATERIAL='" + materialId +"';";
Maybe there is a way to save a previous value of that value? I can not use the quantity of materials as they might be repeated.
I would like to avoid adding IDs to the objects if possible.
This statement:
String sql = "UPDATE MATERIALS set MATERIAL = " + materialId + " where MATERIAL='" + materialId +"';"
Has two (three) problems.
The 'old' value and the 'new' value are the same. You have a logical problem.
WHERE part is concatenated like for string type, but SET part is not
concatenation is evil. The Correct way to do this is
String sql = "UPDATE MATERIALS set MATERIAL = ? where MATERIAL= ?";
PreparedStatement prepstmt = conn.prepareStatement(sql);
prepstmt .setString(1, newMatewrial);
prepstmt .setString(2, oldMaterial);
prepstmt .executeUpdate();
Logical problem must be resolved in your conception.
It Seems the main problem is in basically not using the ID . Every row in relational database should have stable primary key (ID like You say). Name isn't primary key, because can be changed.
WHERE part should use ID and not name.
EDIT: in my opinion good JTable model is one way to solve your problem.
Maybe automagic default table model is too poor. Class implementing Row should have one more column (ID) which can(or not) be invisible.
My English isn't too fluent, cannot teach relational database and Swing in SO post.
The second, small snippet of code doesn't show your application conception.
Read in google about custom JTable model.
Very basic example:
http://www.java2s.com/Code/Java/Swing-JFC/TablewithacustomTableModel.htm
Okay so it seems that I found the solution to the problem
JTable: Detect cell data change
However, this requires implementing another class into the project and using it. The answer for the SQL statement still stays the same.
I am thinking about the design of the method that will enable the user to potentially pass a list of integers that indicate the columns that the user wishes to retrieve from the database.
I do not want to hardcode multiple methods that esentially do the same thing, i.e. show the user different columns but from the same table.
here is the code from Oracle tutorials on retrieving the values using JDBC:
public static void viewTable(Connection con, String dbName)
throws SQLException {
Statement stmt = null;
String query =
"select COF_NAME, SUP_ID, PRICE, " +
"SALES, TOTAL " +
"from " + dbName + ".COFFEES";
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String coffeeName = rs.getString("COF_NAME");
int supplierID = rs.getInt("SUP_ID");
float price = rs.getFloat("PRICE");
int sales = rs.getInt("SALES");
int total = rs.getInt("TOTAL");
System.out.println(coffeeName + "\t" + supplierID +
"\t" + price + "\t" + sales +
"\t" + total);
}
} catch (SQLException e ) {
JDBCTutorialUtilities.printSQLException(e);
} finally {
if (stmt != null) { stmt.close(); }
}
}
So the query is not a problem, the column names can be concatenated, depending on which columns the user wants to see. The issue is in the try block. How does one .get the correct format from the result set? Or should I simply use the String for every column? Or should I hardcode all the table columns (rs.get depending on what data type the column is) and then in println return only the columns that the user wishes to see (actually how would I do that)? Well, I guess you understand my issue.
You can retrieve all the data from the particular table and use it to populate a collection of the appropriate object. And then based on the user's choice, you could just print out the appropriate columns.
Assuming you know how to create the collection of the appropriate object, I will explain how you can do the next step.
You can display a message to the user asking him to enter the columns he wishes to see. Like, Enter 1 to see the coffee name, 2 to see the supplier id, 3 to see the price etc. and 0 to view the data.
So you basically keep reading the int's until the user enters a 0. Once he enters a zero, display the requested values.
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.